مرا اسکن کن!

Service Provider در لاراول چیست

Service Provider در لاراول چیست



یکی از مهمترین قسمت‌های فریم‌ورک لاراول Service Provider ها هست . یه جورایی میشه گفت مغز لاراول هست . چون همه چیز اول اونجا ثبت میشه .

 

Service Provider به زبان ساده

هر برنامه‌ای (حتی غیر لاراولی) برای اینکه اجرا بشه باید چندین کلاس و فایل رو لود و اجرا کنه . سرویس‌هایی مثل کش ، سشن ، کوکی ، دیتابیس و ... از قبل باید لود بشن تا برنامه‌ی ما کار اصلیش رو انجام بده . این لود شدن‌ها توسط قسمت Service Provider ها انجام میشه . این قسمت مسئول پیکربندی و آماده‌سازی پروژه هست . توی این پست با این ویژگی بیشتر آشنا میشیم .

لاراول پرووایدر (Provider) های ما رو از کجا فراخوانی می‌کنه ؟ فایل app.php توی پوشه config رو ببینید ؛ یک آرایه‌ای وجود داره به اسم providers :

'providers' => [

    /*
     * Laravel Framework Service Providers...
    */

    Illuminate\Auth\AuthServiceProvider::class,
    Illuminate\Cache\CacheServiceProvider::class,
    Illuminate\Cookie\CookieServiceProvider::class,
    Illuminate\Database\DatabaseServiceProvider::class,

    // ...

خب همونطور که می‌بینیم پرووایدرهایی مثل Auth , Cache , Cookie و Database اینجا ثبت شدن ! لاراول اول اینها رو لود می‌کنه و بعد برنامه‌ی اصلی ما که وابسته به این سرویس‌ها هست پردازش میشه . یک پرووایدر مثل Auth رو اگه باز کنین می‌بینیم که تنظیمات مربوط احراز هویت اونجا ثبت شده . برای کش و کوکی هم همینطور .

آیا ما به پرووایدر شخصی نیاز داریم ؟

اگه ما به کلاس یا سرویسی نیاز داریم که باید توی برنامه همیشه در دسترس باشه باید اون رو یک جایی ثبت کنیم . اگه تعداد کلاس‌ها و سرویس‌های ما کم باشن اونها رو می‌تونیم توی یک پرووایدر به اسم AppServiceProvider ذخیره کنیم . این پرووایدر از قبل وجود داره و ما توی اون می‌تونیم تنظیمات برنامه رو ثبت یا ویرایش کنیم . و همچنین کلاس‌ها و سرویس‌ها رو رجیستر کنیم . این کلاس توی مسیر app/Providers قرار داره :

class AppServiceProvider extends ServiceProvider
{
    public function register()
    {
        $sms = new SmsNotification;
        $sms->setNumber(0911);
        $sms->setTemplate('...');
        $this->app->instance('SmsNotification', $sms);
    }
}

خب اگه تعداد سرویس‌ها ، تنظیمات و کلاس‌های ما زیاد بشن چطور ؟

class AppServiceProvider extends ServiceProvider
{
    public function register()
    {
        $sms = new SmsNotification;
        $sms->setNumber(0911);
        $sms->setTemplate('...');
        $this->app->instance('SmsNotification', $sms);

        $email = new EmailNotification;
        $email->setTemplate('...');
        $email->setServer('...');
        $this->app->instance('EmailNotification', $email);

        $logger = new Logger;
        $logger->setDriver('file');
        $logger->setRate(30);
        $this->app->instance('Logger', $logger);
    }
}

همونطور که می‌بینیم کلاس‌ها و تنظیمات بی‌ربط کنار هم قرار گرفتن خوانایی و انسجام کد پایین اومده . راه درست اینه کلاس‌ها و تنظیماتی که به هم ارتباط ندارن رو از هم جدا کنیم . برای این کار لاراول به ما اجازه میده که پرووایدر شخصی خودمون رو بسازیم .

 

ساختن یک پرووایدر شخصی

برای ساختن یک پرووایدر شخصی از دستور آرتیزان زیر استفاده می‌کنیم :

php artisan make:provider LoggerServiceProvider

با اجرای این دستور یک فایل به اسم LoggerServiceProvider.php توی مسیر app/Providers برای ما ساخته میشه با محتویات زیر :

namespace App\Providers;

use Illuminate\Support\ServiceProvider;

class LoggerServiceProvider extends ServiceProvider
{
    /**
     * Register services.
     *
     * @return void
     */
    public function register()
    {
        //
    }

    /**
     * Bootstrap services.
     *
     * @return void
     */
    public function boot()
    {
        //
    }
}

متد register مخصوص bind کردن چیزها توی Service Container هست . حالا چیزایی که توی AppServiceProvider نوشتیم رو انتقال می‌دیم به این متد :

class LoggerServiceProvider extends ServiceProvider
{
    public function register()
    {
        $logger = new Logger;
        $logger->setDriver('file');
        $logger->setRate(30);
        $this->app->instance('Logger', $logger);
    }

    // ...
}

تنها کاری که باید انجام بدیم شناسایی کردن این پرووایدر به فریم‌ورک هست . فایل config/app.php رو باز و این پرووایدر رو به آرایه providers اضافه می‌کنیم :

    'providers' => [
        // ...
        \App\Providers\LoggerServiceProvider::class,
    ]

الان این پرووایدر و همه‌ی تنظیمات مربوط به اون توی برنامه در دسترس هست .

 

تفاوت متد register و boot

یکی از چیزهایی که شاید برای خیلیا هنوز گنگ باشه کاربرد این دو متد هست .

یک پرووایدر شامل این دو متد register و boot هست . همونطور که بالاتر گفته شد متد register فقط مخصوص bind کردن و ضمیمه کردن چیزها توی Service Container هست . فریم‌ورک وقتی می‌خواد اجرا بشه ، متد register همه‌ی پرووایدرهایی که ثبت شدن رو اجرا می‌کنه . توی این متد نباید از یک پرووایدر دیگه استفاده کنیم . چون ممکنه این پرووایدر هنوز توسط فریم‌ورک پردازش و لود نشده باشه و توی نوبت باشه . واسه همین ممکنه هنوز در دسترس نباشه .

اما به محض اینکه متد register همه‌ی پرووایدرها پردازش شد ، متد boot همه پرووایدرها توسط فریم‌ورک شروع به پردازش شدن می‌کنه . این رو می‌تونین با یک echo ساده بررسی‌ کنین . پس توی متد boot ما مطمئن هستیم که همه‌ی پرووایدرها رجیستر شدن . پس کارهایی غیر از bind کردن مثل استفاده از یک پرووایدر دیگه ، اضافه کردن فایل‌های Route ، ثبت کردن Event/Listerner ها و ... رو توی متد boot می‌نویسیم .

 

اگه توی یک پرووایدر فقط binding انجام می‌دیم ، یک کار بهینه اینه که این پرووایدر رو deferred کنیم . یعنی این پرووایدر زمانی لود میشه که ما به یکی از binding ها نیاز داریم . این کار باعث سریع‌تر شدن برنامه میشه . برای این کار پرووایدر ما باید اینترفیس DeferrableProvider رو پیاده‌سازی کنه . همچنین یک متد به اسم provides که آرایه‌ای از ‌binding ها رو return می‌کنه رو باید بسازیم :

namespace App\Providers;

use App\Services\Logger;
use Illuminate\Support\ServiceProvider;
use Illuminate\Contracts\Support\DeferrableProvider;

class LoggerServiceProvider extends ServiceProvider implements DeferrableProvider
{
    public function register()
    {
        $this->app->bind(Logger::class, function() {
            return new Logger;
        });
    }

    public function provides()
    {
        return [Logger::class];
    }
}

دقت کنین که بعد از این کار دستور آرتیزان زیر رو وارد کنین :

php artisan clear-compiled

خب این بود همه‌ی چیزایی که باید از سرویس پرووایدرها می‌دونستیم . همونطور که همیشه گفتم این موارد پیاده‌سازی و استفاده‌ی خیلی راحتی دارن اما نکته‌ی مهم‌تر درک کردن این موارد هست . اینکه برای چی به وجود اومدن و چه مشکلی حل می‌کنن . مزایا و معایب استفاده از اونها چیه و ... . دونستن این موارد هست که به یک توسعه‌دهنده‌ی خوب تبدیل میشیم .


نوشته شده توسط :

وحید صمدیان وحید صمدیان



شنبه, 23 مهر 1401

تعداد بازديد : 164

برچسب ها : فریم ورک لاراول

3.0 ستاره