ارائه دهندگان سرویس در لاراول
ارائه دهندگان سرویس محل اصلی برای بوت استرپ کردن برنامه های لاراول هستند. برنامه شما و سرویس های اصلی لاراول توسط ارائه دهندگان سرویس بوت استرپ می شوند. اما منظور از بوت استرپ شدن چیست؟ به طور کلی منظور ثبت کردن چیزهای مختلف از جمله سرویس ها، میان افزارها، مسیرها و غیره است. به عبارت سادهتر ارائه دهندگان سرویس محل اصلی برای پیکربندی برنامه شما هستند.
اگر فایل config/app.php را باز کنید یک آرایه با نام providers را مشاهده خواهید کرد. تمام ارائه دهندگان سرویس مربوط به برنامه شما در آرایه قرار میگرند. سرویس هایی اصلی برنامه مانند AuthServiceProvider، MailServiceProvider، CacheServiceProvider و غیره به صورت پیشفرض در این آرایه قرار دارند. در این بخش شما با نحوه ایجاد و ثبت یک ارائه دهنده سرویس آشنا خواهید شد.
نوشتن ارائه دهنده سرویس (Service Provider)
تمام ارائه دهندگان سرویس از کلاس IlluminateSupportServiceProvider ارث بری می کنند. اغلب آن ها یک متد register و یک متد boot دارند. داخل متد register فقط باید موارد مورد نیاز را در Service Container ثبت کنید. با استفاده از دستور زیر می توانید یک ارائه دهنده سرویس جدید ایجاد کنید:
php artisan make:provider RiakServiceProvider
1 | php artisan make:provider RiakServiceProvider |
متد Register
در ادامه یک ارائه دهنده سرویس پایه و ساده را بررسی می کنیم. در داخل ارائه دهندگان سرویس همیشه به پراپرتی $app (یعنی همان Service Container) دسترسی داریم:
<?php namespace AppProviders; use AppServicesRiakConnection; use IlluminateSupportServiceProvider; class RiakServiceProvider extends ServiceProvider { /** * Register any application services. * * @return void */ public function register() { $this->app->singleton(Connection::class, function ($app) { return new Connection(config('riak')); }); } }
123456789101112131415161718192021 | <?php namespace AppProviders; use AppServicesRiakConnection;use IlluminateSupportServiceProvider; class RiakServiceProvider extends ServiceProvider{ /** * Register any application services. * * @return void */ public function register() { $this->app->singleton(Connection::class, function ($app) { return new Connection(config('riak')); }); }} |
ارائه دهنده سرویس فوق فقط یک متد register تعریف کرده است که با استفاده از آن یک پیادهسازی از AppServicesRiakConnection را در Service Container ثبت می کند.
پراپرتی های bindings و singletons
اگر ارائه دهنده سرویس شما تعداد زیادی از سرویس ها را ثبت می کند، می توانید به جای ثبت آن ها در داخل متد register آن ها را در پراپرتی های bindings و singletons تعریف کنید. آیتم های تعریف شده در پراپرتی های گفته شده در هنگام بارگذاری ارائه دهنده سرویس توسط فریم ورک به طور خودکار بررسی و در Container ثبت می شوند. در مثال زیر نحوه استفاده از این پراپرتی ها را مشاهده می کنید:
<?php namespace AppProviders; use AppContractsDowntimeNotifier; use AppContractsServerProvider; use AppServicesDigitalOceanServerProvider; use AppServicesPingdomDowntimeNotifier; use AppServicesServerToolsProvider; use IlluminateSupportServiceProvider; class AppServiceProvider extends ServiceProvider { /** * All of the container bindings that should be registered. * * @var array */ public $bindings = [ ServerProvider::class => DigitalOceanServerProvider::class, ]; /** * All of the container singletons that should be registered. * * @var array */ public $singletons = [ DowntimeNotifier::class => PingdomDowntimeNotifier::class, ServerProvider::class => ServerToolsProvider::class, ]; }
1234567891011121314151617181920212223242526272829303132 | <?php namespace AppProviders; use AppContractsDowntimeNotifier;use AppContractsServerProvider;use AppServicesDigitalOceanServerProvider;use AppServicesPingdomDowntimeNotifier;use AppServicesServerToolsProvider;use IlluminateSupportServiceProvider; class AppServiceProvider extends ServiceProvider{ /** * All of the container bindings that should be registered. * * @var array */ public $bindings = [ ServerProvider::class => DigitalOceanServerProvider::class, ]; /** * All of the container singletons that should be registered. * * @var array */ public $singletons = [ DowntimeNotifier::class => PingdomDowntimeNotifier::class, ServerProvider::class => ServerToolsProvider::class, ];} |
متد boot
این متد بعد از اینکه تمام ارائه دهندگان سرویس ثبت شدند فراخوانی می شود، به این معنی که در داخل این متد به تمام سرویس هایی که توسط فریم ورک ثبت شدند دسترسی دارید. اگر در داخل این متد به سرویس خاصی نیاز داشتید می توانید مانند نمونه زیر به آن دسترسی داشته باشید:
use IlluminateContractsRoutingResponseFactory; /** * Bootstrap any application services. * * @param IlluminateContractsRoutingResponseFactory $response * @return void */ public function boot(ResponseFactory $response) { $response->macro('serialized', function ($value) { // }); }
1234567891011121314 | use IlluminateContractsRoutingResponseFactory; /** * Bootstrap any application services. * * @param IlluminateContractsRoutingResponseFactory $response * @return void */public function boot(ResponseFactory $response){ $response->macro('serialized', function ($value) { // });} |
ثبت کردن ارائه دهندگان سرویس
تمام ارائه دهندگان سرویس در داخل فایل پیکربندی config/app.php ثبت می شوند. این فایل یک آرایه به نام providers دارد که می توانید مانند نمونه زیر سرویس خود را به آن اضافه کنید:
'providers' => [ // Other Service Providers AppProvidersComposerServiceProvider::class, ],
12345 | 'providers' => [ // Other Service Providers AppProvidersComposerServiceProvider::class,], |
معوق سازی ارائه دهندگان
اگر ارائه دهنده سرویس شما فقط سرویس ها را در Container ثبت می کند، می توانید ثبت آن ارائه دهنده سرویس را تا زمانی که واقعا به آن نیاز باشد، به تعویق بیندازید. به تعویق انداختن چنین ارائه دهنده ای باعث بهبود عملکرد برنامه می شود زیرا برنامه شما برای هر درخواست فایل مربوط به ارائه دهنده را بارگذاری نمی کند.
لاراول لیست ارائه دهندگان معوق را به همراه نام کلاس آن ها ذخیره می کند و زمانی که برنامه درخواست resolve کردن یکی از آن سرویس ها را بکند، ارائه دهنده سرویس مربوطه لود می شود.
برای معوق سازی یک ارائه دهنده سرویس باید اینترفیس IlluminateContractsSupportDeferrableProvider را به همراه متد provides پیادهسازی کنید. متد provides باید سرویس هایی که توسط این ارائه دهنده در Container ثبت می شوند را بازگرداند. برای درک بهتر به مثال زیر توجه کنید:
<?php namespace AppProviders; use AppServicesRiakConnection; use IlluminateContractsSupportDeferrableProvider; use IlluminateSupportServiceProvider; class RiakServiceProvider extends ServiceProvider implements DeferrableProvider { /** * Register any application services. * * @return void */ public function register() { $this->app->singleton(Connection::class, function ($app) { return new Connection($app['config']['riak']); }); } /** * Get the services provided by the provider. * * @return array */ public function provides() { return [Connection::class]; } }
1234567891011121314151617181920212223242526272829303132 | <?php namespace AppProviders; use AppServicesRiakConnection;use IlluminateContractsSupportDeferrableProvider;use IlluminateSupportServiceProvider; class RiakServiceProvider extends ServiceProvider implements DeferrableProvider{ /** * Register any application services. * * @return void */ public function register() { $this->app->singleton(Connection::class, function ($app) { return new Connection($app['config']['riak']); }); } /** * Get the services provided by the provider. * * @return array */ public function provides() { return [Connection::class]; }} |
در مثال فوق ارائه دهنده ما کلاس Connection را در Container ثبت می کند و در داخل متد provides نیز آن کلاس بازگردانده می شود. بنابراین هر زمان که برنامه به کلاس Connection نیاز داشته باشد، ارائه دهنده ما لود خواهد شد.