یوشا

دست نوشته ها و تجربیات شخصی

یوشا

دست نوشته ها و تجربیات شخصی

شهید دکتر مصطفی چمران: می گویند تقوا از تخصص لازمتر است، آنرا می پذیرم، اما می گویم آنکس که تخصص ندارد و کاری را می پذیرد بی تقواست!

طبقه بندی موضوعی

۸۸ مطلب با موضوع «نرم افزار :: برنامه نویسی» ثبت شده است

۰۷
۱۴۰۴/۰۳

زبان برنامه‌ نویسی PHP از زمان معرفی در سال 1994 تا اکنون(2025)، بعنوان یکی از محبوب‌ ترین ابزارها برای توسعه وب در سراسر جهان شناخته شده است. انعطاف‌ پذیری، سادگی یادگیری و فراوانی فریم‌ ورکها، CMF ها و CMS های معروف، آن را به انتخابی ایده‌ آل برای پروژه‌ های کوچک تا متوسط تبدیل کرده است...

اما صرفاً پروژه ها کوچک تا متوسط!

چون وقتی صحبت از محیط‌ ها و محصولات Enterprise-grade (سازمانی) میشود، بحث‌ ها و معیارهای متعدد و چالشی تری درباره مناسب بودن یا نبودن PHP به عنوان ابزار اصلی تولید محصول مطرح می‌ شود... 

با وجود پیشرفت‌ های قابل توجه PHP و فریم‌ ورک‌ هایی مانند Laravel و Symfony، خود زبان PHP همچنان دارای محدودیت‌ هایی است که آن را برای پروژه‌ های Enterprise مناسب نمیکند.

 

در این مقاله به بررسی دلایلی می پردازم که نشان می دهند زبان PHP مناسب محیط ها و محصولات Enterprise نیست. و اینکار را بدون تعصب و با دلایل علمی/فنی انجام میدهم.

  • یوشا آل ایوب
۲۱
۱۴۰۴/۰۱

اگر شما هم از توسعه دهندگان PHP هستید یا با پروژه های مبتنی بر این زبان سروکار دارید، حتماً میدونید که امنیت کدها چقدر اهمیت داره... باگهای امنیتی میتونن به راحتی به یک کابوس برای کسب و کار تبدیل بشن، مخصوصا از نوع باج افزار/Ransomware اش!

اما خب ابزارهایی وجود دارن که به ما کمک میکنن قبل از رسیدن به مرحله production، مشکلات امنیتی رو شناسایی کنیم... یک خانواده از این ابزارها Security linter ها هستن که با اسکن static کدها، حفره ها و اسیب پذیریهای امنیتی رو برنامه نویس ایجاد کرده رو شنایی و گزارش می کنند.

یکی از این ابزارها، PHP Security Linter هستش که دست ساز خودم هست:

 

PHP Security Linter

این ابزار یک Static analysis (تحلیل استاتیک کد) با زبان PHP هست که با اسکن کدها، آسیب پذیری های امنیتی رو بر اساس استانداردهای CIS و OWASP شناسایی میکنه. یعنی بکمک این ابزار و بدون نیاز به اجرای کد، میتونید مشکلاتی مثل SQL Injection، XSS، قرار دادن اطلاعات حساس در کد و غیره... رو پیدا کنید.

 

     

 

آدرس مخزن: https://github.com/Yousha/php-security-linter

 

چرا از این ابزار استفاده کنیم؟

  • پشتیبانی از بیش از ۲۰۰ قانون امنیتی (مطابق با CIS و OWASP)

  • سریع و سبک: بدون اجرای کد، آسیب پذیری ها رو تشخیص میده.

  • پشتیبانی از PHP 7.4 و 8.3 

  • خروجی های متنوع: هم بصورت متن در کنسول و هم JSON.

  • قابلیت شخصی سازی: میتونید قوانین خودتون رو اضافه یا برخی رو غیرفعال کنید.

  • مناسب برای DevSecOps: به راحتی با DevSecOps ادغام میشه.

  • با حداقل dependency و سبک!

 

نصب و استفاده

نصبش بسیار سادست، فقط کافیه با Composer اونرو به پروژه اضافه کنید:

composer require --dev yousha/php-security-linter

بعد برای اسکن یک پوشه:

php vendor/bin/php-security-linter --path ./src

اگرم میخوایید پوشه هایی مثل vendor یا tests رو اسکن نکنید:

php vendor/bin/php-security-linter --path ./app --exclude vendor,tests

 

مثال خروجی ابزار

وقتی اسکن انجام میشه، نتیجه رو به صورت خوانا مشاهده میکنید:

Scan Results
========================================

File: /src/auth.php
  ✗ [CRITICAL] OWASP: SQL Injection vulnerability detected (Line 42)
  ✗ [HIGH] CIS: Hardcoded database credentials (Line 15)

File: /src/utils.php
  ✗ [MEDIUM] OWASP: XSS vulnerability possible (Line 88)

Summary: Scanned 24 files, found 3 potential issues.

 

  • یوشا آل ایوب
۰۵
۱۴۰۳/۱۲

 

OpCache اکستنشنی در PHP هست که برای بهبود پرفورمنس و سرعت پردازش فایلهای PHP ایجاد شده.

این اکستنشن با ذخیره کردن OpCode تولید شده فایلهای PHP در قسمت shared memory حافظه، از بارگذاری و تفسیر مجدد اسکریپت ها در هر درخواست جلوگیری میکنه. و همیشه همون OpCode ذخیره شده رو مصرف میکنه. در نتیجه اسکریپت با سرعت بیشتری پردازش میشه.

در حال حاضر سریعترین، کاملترین و قوی ترین سیستم cache برای PHP اکستنشن opcache هستش که هم optimization و هم caching رو فراهم میکنه.

 

فهرست مندرجات

  • الزامات و نیازمندیها
  • فعالسازی
  • مقایسه OPcache با سایر ابزارهای مشابه
  • نکات
  • تنظیم محیط گرافیکی
  • ابزارهای کمکی در فریمورک ها
  • قابلیت Preloading در PHP 8+
  • رفع مشکلات

  • یوشا آل ایوب
۰۷
۱۴۰۳/۱۱

در CSS، واحدهای سایز به دو دسته/خانواده اصلی تقسیم می‌ شوند:

  1. واحدهای ثابت/Absolute
  2. واحدها متغیر/Relative

 

واحدهای ثابت (Absolute units)

واحدهای ثابت/مطلق به صورت خشک تعریف شده‌ اند و سایز مشخص‌ شده با این واحدها دقیقاً همان اندازه نمایش داده می‌ شود. این واحدها نسبت به اندازه صفحه، جهت یا سایر تغییرات واکنش نشان نمی‌ دهند.

واحدهای ثابت برای استفاده در انواع نمایشگرها توصیه نمیشوند، چراکه اندازه صفحه نمایشها متفاوت است؛ اما در صورتی که محیط خروجی مشخص باشد (مانند Printer)، این واحدها میتوانند مفید باشند.

انواع واحدهای ثابت:

  • cm (سانتی‌ متر)
  • mm (میلی‌ متر)
  • in (اینچ)
  • px (پیکسل)
  • pt (پوینت)
  • pc (پیکا)
  • q (یک چهارم میلی‌ متر)

مثال:

/* یک باکس با عرض 2 سانتی‌ متر */
.box {
    width: 2cm;
    height: 2cm;
    background-color: lightblue;
}

/* متن با اندازه فونت ثابت 12 پوینت */
.text {
    font-size: 12pt;
}

 

واحدهای متغیر (Relative units)

واحدهای متغیر/مقیاس پذیر سایز را بصورت خودکار و نسبت به ویژگیهای دیگر مانند اندازه صفحه نمایش، اندازه صفحه مرورگر، عناصر والد/parent و... تنظیم میکنند. این واحدها در بین انواع دستگاه های مختلف بهتر scale و تنظیم میشوند.

انواع واحد های متغیر:

  • em : نسبت به اندازه فونت عنصر والد تنظیم میشود
  • ex : نسبت به ارتفاع x در فونت جاری، که برای فونتهای تک‌ فاصله مفید است تنظیم میشود
  • ch : نسبت به عرض کاراکتر "0" در فونت عنصر، برای فونت‌ های تک‌ فاصله کاربرد دارد
  • rem : نسبت به اندازه فونت عنصر ریشه (<html>)
  • vw : نسبت به 1٪ از عرض پنجره مرورگر
  • vh : نسبت به 1٪ از ارتفاع پنجره مرورگر
  • vmin : نسبت به 1٪ از کوچک‌ ترین بُعد پنجره مرورگر
  • vmax : نسبت به 1٪ از بزرگ‌ ترین بُعد پنجره مرورگر
  • % : نسبت به عنصر والد تنظیم میشود

 

توضیحات تکمیلی واحدهای مهم

  • px (پیکسل) - ثابت

    • پیکسل یک مربع کوچک روی نمایشگر است که می‌تواند فقط یک رنگ را در یک لحظه نمایش دهد. مانند عدد رزولوشن نمایشگر که نشان‌ دهنده تعداد پیکسل‌ های تشکیل‌  دهنده صفحه است. 1024x768
    • font-size: 12px; به مرورگر می‌ گوید که ارتفاع هر کاراکتر 12 عدد پیکسل باشد. پیکسل ها اندازه ثابتی دارند و تغییر اندازه نمی‌ دهند. این واحد برای مواقعی که نیاز به قرار دادن متن روی یک تصویر پس‌ زمینه دارید، مفید است.
  • % (درصد) - متغیر

    • درصد یک واحد متغیر است که بر اساس اندازه عنصر والد محاسبه می‌شود. برای تعیین عرض یا ارتفاع عناصر، زمانی که والد مشخص باشد، می‌ تواند به عنوان راهی منعطف استفاده شود.
    • font-size: 50%; اندازه فونت را به ۵۰٪ اندازه فونت عنصر والد تنظیم میکند.
    • font-size: 100%; یعنی ۱۰۰٪ اندازه‌ ای که از عنصر والد به ارث می برد. درصد برای طراحی‌ های انعطاف‌ پذیر مناسب‌ تر است.
    • در CSS، هر چیزی که از این واحد استفاده کند، نسبت به عنصر والد خود است، مگر در حالتی که موقعیت عنصر ثابت باشد که در آن صورت نسبت به عنصر ریشه <html> خواهد بود.
    • نکته: تعیین width یا height به درصد زمانی عمل نمی‌ کند که ابعاد عنصر والد بطور auto تعیین شده باشد.
  • pt (پوینت) - ثابت

    • 1 پوینت برابر با ۱/۷۲ اینچ است. font-size: 12pt; ارتفاع کاراکترها را به ۱۲/۷۲ اینچ تنظیم می‌ کند. پوینت اندازه‌ ای ثابت دارد و مقیاس‌ پذیر نیست!
    • پوینت در طراحی Print استفاده می‌شود و تنها در CSS مربوط به @media print کاربرد دارد.
  • em - متغیر

    • این واحد شبیه به درصد است و نسبت به اندازه فونت عنصر والد محاسبه می‌شود. اما ۱em برابر با ۱۰۰٪ و ۱.۵em برابر با ۱۵۰٪ است. em یک واحد مقیاس‌ پذیر است و برای تعیین اندازه فونت مناسب اما چالشی است.
    • یک em برابر با اندازه فونت جاری است، به عنوان مثال اگر اندازه فونت کل صفحه 12pt باشد، 1em برابر با 12pt خواهد بود. این واحد مقیاس‌ پذیر است؛ بنابراین 2em برابر با 24pt، ۰.۵em برابر با 6pt خواهد بود.
  • rem - متغیر

    • واحد rem هم مانند em مقیاس‌ پذیر است اما همیشه نسبت به اندازه فونت عنصر ریشه <html> محاسبه می‌ شود، که باعث می‌ شود از تغییرات ناخواسته در طراحی جلوگیری کند. بنابراین با استفاده از عناصر تودرتو دیگر نیازی به محاسبه اندازه فونت در رابطه با عنصر والد نیست. برای تعیین اندازه فونت مناسب است.
  • cm، mm، in - ثابت
    • معمولاً برای اندازه‌ گیری‌ های دقیق در محیط‌ های غیر دیجیتال و فیزیکی مانند Print به کار می‌ روند. اندازه فونت با تغییر اندازه پنجره مرورگر به صورت دینامیک واکنش نشان نمی‌ دهد، بلکه به تنظیمات زوم یا اندازه متن مرورگر، مانند فشار دادن همزمان کلید Ctrl و + در مرورگر، واکنش نشان می‌دهد.
  • vm. vh. viewport... - متغیر
    • واحدهای vw و vh نسبت به عرض و ارتفاع صفحه نمایش تعریف می‌ شوند. درواقع درصدی از پنجره مرورگر را نشان می‌ دهند و برای طرح‌ های واکنش‌ گرا کاربرد دارند. 1vw معادل 1٪ از عرض صفحه نمایش و 1vh معادل 1٪ از ارتفاع صفحه نمایش است. این واحدها به خصوص برای طراحی‌ های تمام‌ صفحه بسیار مفیدند.

مثال:

/* با عرض برابر با 50% از عرض پنجره مرورگر */
.box {
    width: 50vw;
    height: 50vh;
    background-color: lightcoral;
}

 

کاربرد واحدها در عناصر وب

  • px (پیکسل): برای اندازه خطوط مرزی و اجزای کوچک ثابت.

    • کاربرد: <button>, <small>, خطوط و حاشیه‌ ها.
  • % (درصد): برای تنظیم ابعاد نسبی نسبت به عنصر والد، به ویژه در عرض و ارتفاع.

    • کاربرد: <div>, <img>, <section>, <header>, <footer>.
  • em: برای تنظیم اندازه فونت و فاصله‌ های داخلی، با توجه به اندازه فونت والد.

    • کاربرد: <p>, <span>, <ul>, <ol>.
  • rem: برای اندازه فونت اصلی در کل صفحه و مقیاس‌ پذیری یکنواخت، بدون تاثیر از والد.

    • کاربرد: <body>, <h1>, <h2>, <h3>, <html>.
  • vw و vh: برای تنظیم ابعاد نسبی کل صفحه نمایش، به خصوص در طراحی‌ های تمام صفحه.

    • کاربرد: <section>, <header>, <footer>, عناصر تمام صفحه.
  • pt: برای فونت در خروجی چاپ (به ندرت برای وب).

    • کاربرد: فقط در چاپ، مثل استایل تحت @media print.
  • cm, mm, in: برای موارد خاص Print و اندازه‌ گیری دقیق.

    • کاربرد: چاپ و طرح‌ های خاص، مثل استایل‌ های PDF و کارت ویزیت

 

توجه: در اکثر مرورگرها، اندازه پیش‌ فرض فونت صفحه 16px است.

  • یوشا آل ایوب
۱۱
۱۴۰۳/۱۰

1- مفهوم و تفاوت Concurrency(همزمانی) و Parallel(موازی):

- پردازش Parallel نوعی از Concurrent هستش. درواقع Parallel زیرمجموعه Concurrency هستش.

- نوع Concurrent میتونه با یک پردازنده اعمال بشه (single/multi thread). اما نوع Parallel باید در چند پردازنده اعمال بشه. یعنی یک پردازنده به ازای هر پروسس.

نکته: عمل Multithreading زیرمجموعه Concurrency محسوب می‌شه و می‌تونه با پردازنده‌های تکی هم انجام بشه.

 

2- با استفاده از کلمه کلیدی volatile در متغیرها می تونید thread های برنامه رو وادار کنید تا اطلاعات متغیر رو مستقیماً از حافظه بخونن و نه کش CPU. (این عمل درواقع نوعی thread-safety محسوب میشه)

 

3- یادتون باشه که synchronized و Thread-Safe در .Net یک مفهوم دارن: دسترسی همزمان به کد توسط چند Thread بدون بروز مشکلات. یعنی کد/متد synchronized اجازه دسترسی همزمان چند Thread به کد/متد رو نمیده، پس Thread ها باید نوبتی به کد/متد دسترسی پیدا کنن بنابراین آخرین وضعیت کد/متد در همه Thread ها مشترک هستش.

نکته: این مسئله فقط در مورد برنامه های Multi-Thread صدق میکنه و نه Single-Thread.

نکته 2: در .Net باید از تکنیک‌هایی مانند lock برای Thread-Safe کردن کد استفاده کرد.

  • یوشا آل ایوب
۱۸
۱۴۰۳/۰۹

دلایل مختلفی ممکنه وجود داشته باشه که یک تیم توسعه‌ دهنده تصمیم بگیره قابلیت API رو از یک پروژه‌ی Laravel حذف کنه... مثلا:

 

- نیاز نداشتن به API و تمرکز روی توسعه‌ وب‌ سایت

- کاهش پیچیدگی و تمیزکاری

- کاهش دردسرهای امنیتی

- بهبود مصرف منابع سرور

 

خلاصه اگه واقعاً API به کار نیاد، حذفش باعث سبکتر شدن پروژه، ساده‌ تر شدن نگهداری و تمرکز بیشتر روی همون کار اصلی میشه.

برای حذف اصولی API و موارد مرتبط از یک پروژه Laravel، باید مراحل زیر رو انجام داد:

 

1- حذف فایل API از Route ها

مسیرهای API معمولاً در فایل routes/api.php تعریف میشن. این فایل رو باید پاک کنید.

routes/api.php

 

2- حذف Loader فایل api.php در RouteServiceProvider

مسیر:

app/Providers/RouteServiceProvider.php

کدها:

public function boot()
{
    $this->routes(function () {
        // این قسمت رو حذف یا کامنت کنید
        // Route::middleware('api')
        //     ->prefix('api')
        //     ->group(base_path('routes/api.php'));

        Route::middleware('web')
            ->group(base_path('routes/web.php'));
    });
}

 

3- حذف middleware های مربوط به API در Kernel.php

مسیر:

app/Http/Kernel.php

کدها:

protected $middlewareGroups = [
    'web' => [
        // Middlewareهای وب
    ],

    // این قسمت رو حذف یا کامنت کنید
    // 'api' => [
    //     \Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class,
    //     'throttle:api',
    //     \Illuminate\Routing\Middleware\SubstituteBindings::class,
    // ],
];

 

4- درصورت وجود: پاک کردن کنترلرها و منابع API

مسیر:

app/Http/Controllers/API
و
app/Http/Resources

 

5- پاک کردن cache ها

دستور زیر رو بزنید تا cache ها پاکسازی بشن:

php artisan optimize:clear

 

6- حذف دستورات پکیج Sanctum

مسیر:

app\Models\User.php

کدها:

   //use Laravel\Sanctum\HasApiTokens;

   final class User extends BaseUser
   {
      //use HasApiTokens;

اگر از این Trait در مسیرهای دیگه هم استفاده شده، حذفش کنید.

 

7- کانفیگ Path در CORS

مسیر:

config\cors.php

کدها:

'paths' => ['api/*', 'sanctum/csrf-cookie'], // -> 'paths' => [],

 

8- حذف فایل کانفیگ پکیج Sanctum و Passport

مسیر:

config\sanctum.php
و
config\passport.php

 

9- حذف کدهای Sanctum و Passport از داخل فایلهای tests

مسیر:

tests/unit/
و
tests/feature/

 

10- حذف کدها و جدول personal_access_tokens

جدول personal_access_tokens رو از دیتابیس حذف کنید. همچنین:

مسیر:

routes\console.php

کدها:

//DB::table('personal_access_tokens')->truncate();

 

11- نهایتاً حذف پکیج laravel/sanctum و laravel/passport

دستور:

composer remove laravel/sanctum
composer remove laravel/passport

و مجدد دستور زیر رو بزنید تا cache ها پاکسازی بشن:

php artisan optimize:clear
  • یوشا آل ایوب
۰۹
۱۴۰۳/۰۶

برخی از مهمترین معیارهای انتخاب زبان برنامه نویسی: Java, .Net, PHP

(برای بزرگنمایی کلیک کنید)

  • یوشا آل ایوب
۱۷
۱۴۰۳/۰۳

یکی از مهمترین ویژگی‌ های جدید در PHP 8.0، کامپایلر JIT است. JIT می‌تواند با کامپایل کردن و ذخیره‌ کردن کامل یا بخش‌ هایی از اسکریپت PHP، به کد ماشین CPU، عملکرد را بسیار بهبود بخشد و به طور مستقیم کد ماشین را اجرا کند، بطوریکه Zend VM و سربار ناشی از عملیات و فرایندهای آنرا دور می‌ زند و نادیده می‌ گیرد.

JIT ترکیبی از مفسران traditional و کامپایلرهای AoT است. این مدل ترکیبی/Hybrid، مزایا و معایب هر دو مفسر و کامپایلر را به ارمغان می‌آورد.
پیاده‌ سازی PHP JIT تنها با تلاش‌ های شگفت‌ انگیز Dmitry Stogov در چند سال اخیر، ارزش بحث، اجرا و آزمایشات را پیدا کرده است.

این مقاله در مورد benchmark ها، نحوه‌ی کار JIT، امکانات و گزینه‌ های پیکربندی در php.ini می باشد.

دانلود مقاله PDF

  • یوشا آل ایوب
۰۱
۱۴۰۱/۱۱

Contents

  • Introduction

  • Types of packages

  • Characteristics of a package

  • The Laravel package!

  • Components of a Laravel package

  • Example of a Laravel package

  • Creating your Laravel package

    • 1- Package structure

    • 2- Required equipments

    • 3- Create package structure

    • 4- Update package manifest

    • 5- Create route

    • 6- Create configuration file

    • 7- Create command for package

    • 8- Create controller

    • 9- Create middleware

    • 10- Create [database] migration

    • 11- Create view

    • 12- Create [view] assets

    • 13- Create service provider

    • 14- Create a manual/help file

    • 15- Build our package

    • 16- Test/Use our package

  • Best practices

  • Publish your Laravel package

  • Conclusion

Introduction

In context of software development - particularly with PHP - a package is a modular, reusable piece of functionality that can be integrated into an application. Packages are designed to extend or enhance capabilities of a application by adding specific features or tools without reinventing wheel!

Now why use packages instead of developing built-in code and features?

Because:

  • Save time & effort: Instead of coding complex functionality (like payments, authn, or APIs), you use a well-tested package, by too many users (well-cooked)
  • Follow best practices: Good packages are built by experts(mostly), ensuring security, performance, and maintainability.
  • Easy updates: When a package improves, you get upgrades without rewriting your code. (composer update vendorname/packagename)
  • Community-Powered: Many packages are open-source, meaning developers worldwide contribute to improve them.

So let's avoid reinventing wheel!


Types of packages

Each type of package solves problems at different levels - from tiny utilities, authn, dev tools to massive libraries - all shareable through dependency manager(like Composer) and designed to work harmoniously in your project ecosystem. These types are:

  1. Standalone packages: AKA framework-agnostic packages, these are general-purpose packages that can be used with/without any PHP framework. Like guzzlehttp, monolog, redbean, etc...

  2. Framework-Specific packages: These are tailored specifically for framework(Laravel, Symfony, YAF...) and leverage its features, such as service providers, facades, and configuration systems. Like spatie/laravel-permission, wordpress plugins, symfony/console, codeigniter4/cache, etc...


Characteristics of a package

A package is defined by following key characteristics:

  • Reusability: A package encapsulates functionality that can be reused across multiple applications.

  • Modularity: It is self-contained, meaning it includes all necessary components (like routes, controllers, views, configuration files) to perform its intended function.

  • Dependency management: Application's packages often rely on Composer, PHP's dependency manager, for installation and version control.

These traits ensure that packages maintain consistency, reduce redundancy, and simplify integration in software development.


Laravel logo

The Laravel package!

A Laravel package is like a ready-made toolbox that adds extra features to our Laravel application. This can be a kind of Open-Close principle... Instead of building everything from scratch, you can install a package to quickly add things like:

  • Authentication (signin/signup/signout)

  • Payment processing (Stripe, PayPal)

  • File uploads

  • API tools

  • Admin dashboards

  • etc...

Packages save you time and let you focus on our application's unique parts. They’re easy to install (usually via Composer) and often come with clear instructions(I hope :D).
Think of them as "plugins" for Laravel!


Components of a Laravel package

A Laravel package is made up of several key components that work together to extend our application's functionality. It bundles some components to provide reusable functionality. Once structured correctly, users/developers can install it via Composer and integrate it seamlessly into their applications...

Here is components of a Laravel package:

  1. Service Provider: "bridge" between our package and Laravel. Registers our package’s services, routes, views, and configurations.

  2. Configuration file: A config file (usually config/mypackagename.php) where users/developers can customize package settings.

  3. Routes: Defines web or API routes for our package.

  4. Migrations: Database tables and required records/rows needed by our package. (if our package needs data storage)

  5. Views: Frontend components (HTML mostly) stored in resources/views/.

  6. Controllers: Handles logic and processes requests. Like a microcontroller in electronic world!

  7. Models: Interacts with database. Mirror of a table in database. (if our package needs data storage)

  8. Assets: Frontend assets (JavaScript, CSS, images) stored in resources/assets/.

  9. Commands: Custom Artisan commands for package-specific tasks. Like php artisan mypackagename:install

  10. Facades: Provides a simple interface to our package features. Like MyPackageName::doSomething()

  11. Middleware: Adds request/response filtering for our package. Like authn checks.

  12. Tests: PHPUnit or Pest tests to ensure reliability and QA.

  13. Composer.json: Defines package dependencies, autoloading, and metadata... (something like manifest)

Note that some of components are optional and can be ignored in packages.


Example of a Laravel package

Now here's a great example of a popular Laravel package to quick-start: Laravel Horizon
It provides a beautiful UI for managing our Redis queues... What it does, gives us a cool dashboard and powerful tools to monitor and manage our Laravel queues. It's like having mission control for our background jobs.

Installation
composer require laravel/horizon

Configuration
php artisan horizon:install

Usage
Access the dashboard at http://domain/horizon (behind authn by default)

See? too easy!

This Laravel package is perfect for apps that handle email processing, report generation, or any heavy background tasks...


Creating your Laravel package

Laravel packages let you encapsulate reusable functionality - whether it's a handy utility, a full-featured module, or an integration with an external service. By creating your own package, you can share code across projects, maintain clean architecture by separating concerns, contribute to open-source and boost your dev cred!

To create your own Laravel package, you should simply: setup the package structure, define a service provider, publish assets, test the package, and finally distribute via Packagist. That's all

Let's start!

1- Package structure

The structure of our package will be something like this:

All components were explained in section "Components of a Laravel package" above.

my-package/
├── src/
│   ├── MyPackageServiceProvider.php
|   ├── Http/
│   │   ├── Middleware/
│   │   │   └── ExampleMiddleware.php
│   │   └── Controllers/
│   │       └── ExampleController.php
│   ├── Console/
│   │   └── Commands/
│   │       └── ExampleCommand.php
│   ├── migrations/
│   │   └── 2023_12_05_000000_create_examples_table.php
│   ├── resources/
│   │   ├── views/
│   │   │   └── example.blade.php
│   │   └── assets/
│   │       └── css/
│   │           └── example.css
│   ├── config/
│   │   └── my-package.php
│   └── routes/
│       └── web.php
├── composer.json
└── README.md

And yes, we are keeping config, database, routes, and resources directories INSIDE src directory. Because this style is a self-contained structure, simpler publishing, and fits small projects.

But keeping config, database, routes, and resources directories OUTSIDE src directory fits large or public packages, aligns with Laravel community standards, and ensures PSR-4 compliance.

Note: Both styles are valid, but decision depends on your package's purpose and audience... For most developers, especially those contributing to Laravel ecosystem, outside src structure is preferred because it adheres to widely accepted conventions and improves maintainability. However, for internal or smaller projects, inside src structure can offer simplicity and encapsulation.

2- Required equipments

1- Infrastructure: PC! (laptop or desktop)

2- Platform: Windows or GNU/Linux OS

3- Interpreter: PHP >= 7.4

4- Dependency manager: Composer

5- Editor/IDE: Apache Netbeans, Ms VSCode, Eclipse IDE, Notepad++, Vim, etc...

6- Web server: Apache HTTPD, NGINX, PHP's built-in server

3- Create package structure

Now create all directories and files(empty) like above... To do this, you can use composer init and answer questions to bootstrap our package.

Or open system terminal/CMD and use mkdir dirname, touch filename, echo > filenamecommands to create them manually.

Or download & run my shell scripts to generate them for you: Windows BATCH, GNU/Linux BASh

4- Update package manifest

Now we must update our composer.json file for package needs:

{
   "name": "example/my-package",
   "description": "A simple Laravel package for example.",
   "type": "library",
   "version": "1.0.0",
   "authors": [
      {
         "name": "Your Fullname",
         "email": "name@domain.tld"
      }
   ],
   "require": {
      "php": "7.4.*",
      "illuminate/support": "10.*",
      "illuminate/console": "10.*",
      "illuminate/database": "10.*",
      "illuminate/routing": "10.*"
   },
   "autoload": {
      "psr-4": {
         "Example\\MyPackage\\": "src/"
      }
   },
   "extra": {
      "laravel": {
         "providers": [
            "Example\\MyPackage\\MyPackageServiceProvider"
         ]
      }
   }
}

Some explanation:

  • "version" tag will be match with your Git's repository tag.

  • "psr-4" tag defines how PHP classes are designed and autoloaded. Look for classes by PSR-4 STYLE in that folder when I use this namespace.

  • "Example\\MyPackage\\" tag is our logical(inside codes) path which maps to our "src/" physical(filesystem) path.

  • "laravel": {"providers"... tags are for Laravel-specific packages (uses Laravel features). And it's auto-registers our ServiceProvider when someone installs our package via Composer.

Note: When creating a Laravel package, you do NOT need to require the entire laravel/framework in your manifest file composer.json. Instead, you should only require the specific components("illuminate" packages) that your package depends on. By this way your package remains lightweight and does not include unnecessary of dependencies on the projects that use it. (avoid dependency hell!)

5- Create route

File src/routes/web.php:

<?php

use Illuminate\Support\Facades\Route;
use Example\MyPackage\Http\Controllers\ExampleController;

Route::get('/example', [ExampleController::class, 'index'])
   ->middleware('example.middleware') // Apply our middleware directly. Type: Route Middleware
   ->name('example.index');           // Assign a name to the route.

Some explanation:

'/example' our package's feature URL.

'index' our ExampleController's method to call.

->name('example.index') a unique name for that route/URL. So we can call it anywhere instead of hardcoding it's URL. Can be used in:

// Blade template
<a href="{{ route('example.index') }}">Example</a>
// Controller
return redirect()->route('example.index');
// Middleware or services
$url = route('example.index');
// Testing (PHPUnit)
$response = $this->get(route('example.index'));

6- Create configuration file

File src/config/my-package.php:

<?php

return [
   'greeting' => 'Awesome hello from MyPackage!!',
];

A complex config!

7- Create command for package

This command can be used by user/developer in their Laravel application.

File src\Console\Commands\ExampleCommand.php:

<?php

namespace Example\MyPackage\Console\Commands;

use Illuminate\Console\Command;

class ExampleCommand extends Command
{
   protected $signature = 'my-package:example'; // The command that user uses and run.
   protected $description = 'An example command description for MyPackage.';

   public function handle()
   {
      // Example logic.
      $this->info('Hello from MyPackage command!');
   }
}

Example usage in Laravel application: php artisan my-package:example

8- Create controller

File src/Http/Controllers/ExampleController.php:

<?php

namespace Example\MyPackage\Http\Controllers;

use Illuminate\Routing\Controller;
use Illuminate\Support\Facades\Config;

class ExampleController extends Controller
{
   public function index()
   {
      $greeting = config('my-package.greeting');
      return view('my-package::example', compact('greeting'));
   }
}

The double colon (::) in view('my-package::example') is Laravel's syntax for package views, and it prevents naming collisions.

Because imagine our package has example.blade.php file, and the main app(consumer) also has example.blade.php file...! so that namespace ensures Laravel uses the correct file.

  • my-package = Our package's view namespace (registered via loadViewsFrom())

  • example = The view file name (without .blade.php)Because using the namespace (::) prevents naming collisions.

Note: For better organization, always put all HTTP protocol related classes (Controllers) under /Http/ directory.

9- Create middleware

A middleware is a gatekeeper for HTTP requests in our package. It checks, modifies, or blocks requests before they reach our routes/controllers.

There are 3 types of middlewares:

  1. Global = Runs on every HTTP request, like CORS headers, applies in Kernel.php file.

  2. Route = Runs on specific routes, like Authentication & role checks, applies in routes files.

  3. Group = Runs on routes in a named group, like API auth & web session handling, applies in routes files.

File src/Http/Middleware/ExampleMiddleware.php:

<?php

namespace Example\MyPackage\Http\Middleware;

use Closure;
use Illuminate\Support\Facades\Response;

class ExampleMiddleware
{
   public function handle($request, Closure $next)
   {
      // Example logic.
      if ($request->has('allow')) {
         return $next($request);
      }

      return response('Access Denied! XD', 403);
   }
}

Then register the middleware in the our package's service provider, inside boot() method.

File src/MyPackageServiceProvider.php:

class MyPackageServiceProvider extends ServiceProvider
{
   public function boot()
   {
      // Register our package's middleware.
      $this->app['router']->aliasMiddleware('example.middleware', ExampleMiddleware::class);

In Laravel, middlewares are typically registered in boot() method of a service provider rather than register() method... because:

  • register() method is primarily used for binding services into container. Since middlewares DO NOT need to be bound into the service container, this method isn't suitable for middleware registration.

  • boot() method is where middleware should be registered, because it gets executed AFTER all services have been registered. So middlewares consumes those services!

Another thing, it doesn't technically matter if you put middleware at top or bottom of boot() method, but there's best practices to put middleware at the TOP of boot() if:

  • It's essential for other package features (routes, controllers, etc.)

  • It's a global middleware (runs on every request)

Note: For better organization, always put all HTTP protocol related classes (Middleware) under /Http/ directory.

10- Create [database] migration

File src/migrations/2023_12_05_000000_create_examples_table.php:

<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class CreateExamplesTable extends Migration
{
   public function up()
   {
      Schema::create('examples', function (Blueprint $table) {
         $table->id();
         $table->string('name');
         $table->timestamps();
      });
   }

   public function down()
   {
      Schema::dropIfExists('examples');
   }
}

Note that Laravel will automatically include our package's migrations...

Blueprint, really nice class name.

11- Create view

File src/resources/views/example.blade.php:

<!DOCTYPE html>

<html>
<head>
    <title>MyPackage</title>
    <link rel="stylesheet" href="{{ asset('vendor/my-package/css/example.css') }}">
</head>

<body>
    <h1>{{ $greeting }}</h1>
</body>
</html>

This asset/CSS will resolve to http://<domain>/vendor/my-package/css/example.css URL.

12- Create [view] assets

File src/resources/assets/css/example.css:

body {
   font-family: Arial, sans-serif;
   background-color: #f4f4f4;
   text-align: center;
   padding: 50px;
}

h1 {
   color: #268f22;
}

13- Create service provider (the bridge)

The service provider is the entry point of package. It registers routes, middleware, commands, and other components...

File src/MyPackageServiceProvider.php:

<?php

namespace Example\MyPackage;

use Illuminate\Support\ServiceProvider;
use Illuminate\Support\Facades\URL;
use Example\MyPackage\Console\Commands\ExampleCommand;
use Example\MyPackage\Http\Middleware\ExampleMiddleware;

class MyPackageServiceProvider extends ServiceProvider
{
   public function boot()
   {
      // Register our middleware.
      $this->app['router']->aliasMiddleware('example.middleware', ExampleMiddleware::class);

      // Publish configuration file.
      $this->publishes([
         __DIR__ . '/config/my-package.php' => config_path('my-package.php'),
      ], 'config');

      // Register migrations.
      $this->loadMigrationsFrom(__DIR__ . '/migrations');

      // Register routes.
      $this->loadRoutesFrom(__DIR__ . '/routes/web.php');

      // Register views.
      $this->loadViewsFrom(__DIR__ . '/resources/views', 'my-package');

      // Publish assets.
      $this->publishes([
         __DIR__ . '/resources/assets/' => public_path('vendor/my-package'),
      ], 'assets');

      // Publish assets.
      $this->publishes([
         __DIR__ . '/migrations' => database_path('migrations'),
      ], 'migrations');  // <- The tag is defined here will be used in `php artisan vendor:publish --tag=HERE` command.

      // Register commands.
      if ($this->app->runningInConsole()) {
         $this->commands([
            ExampleCommand::class,
         ]);
      }
   }

   public function register()
   {
      // Merge configuration.
      $this->mergeConfigFrom(
         __DIR__ . '/config/my-package.php',
         'my-package'
      );
   }
}

Some explanation:

  • $this->loadRoutesFrom / $this->loadViewsFrom / $this->loadMigrationsFrom: These lines tells to Laravel that my package has some route/view/migration definitions in those files... So load them into your application.

  • $this->publishes: This lines copies files/folders from our package's resources/migration/route directory to the Laravel app's folders. That's all!

  • public_path('vendor/my-package'): This will copy files from resources/assets (inside our new package) to public/vendor/my-package of consumer/app.

14- Create a manual/help file

It is best to create a README.md file to help users of your package with following sections: about, installation, publishing, configurations, migrations, commands, usage, license etc...

15- Build our package

To make our package ready, go to package's root directory and run the following commands:

composer install

^ Installs package dependencies.

composer dump-autoload

^ Update autoloader after adding new classes.

16- Test/Use our package (locally)

For this, we create a new Laravel application to use/consume our Laravel package.

So let's create a new Laravel application:

composer create-project "laravel/laravel:10.*" my-laravel-app

Now open application's manifest file composer.json, and add the following lines:

"repositories": [
    {
        "type": "path",
        "url": "../myfolder/my-package"
    }
]

In this file, we tell Composer about an additional package repository (other than Packagist.org) that is stored locally on the system. Composer will use this repository to find and install packages... so URL must be correct & address our package to the application.

Then normally install our package inside this new Laravel app:

composer require example/my-package

And update autoloader after adding new classes: (app)

composer dump-autoload

So our package is added into the application, but NOT published(copy its stuff) yet.

To verify our package's service provider is loaded in Laravel application: (app)

php artisan package:discover

It must give you something like this: (app)

example/my-package ............................... DONE
  laravel/sail ............................................... DONE
  laravel/sanctum ........................................ DONE
  laravel/tinker ............................................ DONE
  nesbot/carbon ........................................... DONE
  nunomaduro/collision ................................ DONE
  nunomaduro/termwind ............................... DONE
  spatie/laravel-ignition ................................. DONE

Now run the following commands to publish/copy our package config/assets/migrations inside the application: (app)

php artisan vendor:publish --tag=config

php artisan vendor:publish --tag=assets

php artisan vendor:publish --tag=migrations

Finally, run application's migrations(if any) then clear ALL caches: (app)

php artisan migrate

php artisan optimize:clear

Best practices

Here are a few short best practices when creating a package:

  • Testing: Always write unit tests, using PHPUnit or Pest libraries.

  • Documentation: Include a detailed README.md file in your package's root directory. (Add Overview, Installation, Configuration, Usage, Testing, Contributing...)

  • Versioning: Use SemVer or any other versioning standard (Major.Minor.Micro.Build).

  • PSR standards compliance: Follow PSR-12 coding standards.

  • Security: Validate inputs in middleware/controllers and use CSRF protection.


Publish your Laravel package

Once your Laravel package is complete, tested, and ready for public use, you can submit it to Packagist.org , the official PHP package repository for Composer tool. This allows developers around the world to install your package via a simple command:

composer require example/my-package

Conclusion

Packages streamline Laravel development by promoting reuse and modularity. Follow this guide to create, test, and share your own! Contribute to open-source and avoid "dependency hell" by requiring only essential illuminate/* components.

Project repository

Download Zip or TArGz

Helpful information

Essential commands after package creation:

  • In your package 
Command Purpose
composer install Install package dependencies
composer dump-autoload Update autoloader after adding new classes

 

  • In your application (consumer)
Command Purpose
composer require vendor/package-name Install the package
composer dump-autoload Refresh autoloader to detect new classes
php artisan package:discover Auto-register package service providers
php artisan vendor:publish --tag=package-config Publish config files (if any)
php artisan vendor:publish --tag=package-migrations Publish migration files (if any)
php artisan vendor:publish --tag=assets Publish asset files (if any)
php artisan migrate Run packages migrations
php artisan optimize:clear Clear all caches (routes, views, config)
  • یوشا آل ایوب
۰۸
۱۴۰۱/۰۹

تعریف جرمیابی دیجیتال: به مجموعه فرایند جمع آوری، ارزیابی و ارائه مدارک جمع آوری شده از تجهیزات دیجیتال گفته میشود.

این مدارک دیجیتالی از کامپیوترها، تلفن های همراه، دستگاه های اینترنت اشیا و سرورها به دست می آیند. جرمیابی دیجیتال به حل پرونده های پیچیده ای که بر مدارک دستگاه های دیجیتالی تکیه دارند کمک می کند.

این حوزه کاری زیر مجموعه امنیت سایبری می باشد و به فرد متخصصی که در این حوزه کار میکند متخصص جرمیابی دیجیتال و واکنش به حوادث گفته میشود.

(به انگلیسی Digital Forensics and Incident Response (DFIR))

 

برای بزرگنمایی کلیک کنید

  • یوشا آل ایوب