Laravel 8: Tìm hiểu về Service Provider

Giới thiệu Các service trong ứng dụng Laravel đều được khởi động thông qua Service Provider. Cụ thể, quá trình khởi động service ở đây là đăng ký các Service Container binding, event listener, middleware hay route… Mỗi component sẽ có một service provider làm nhiệm vụ đăng ký key (sau khi binding) hoặc kích

Giới thiệu

Các service trong ứng dụng Laravel đều được khởi động thông qua Service Provider. Cụ thể, quá trình khởi động service ở đây là đăng ký các Service Container binding, event listener, middleware hay route… Mỗi component sẽ có một service provider làm nhiệm vụ đăng ký key (sau khi binding) hoặc kích hoạt một số hàm (sau khi framework boot).

Để thấy rõ hơn điều này, bạn hãy mở file config/app.php. Bạn sẽ thấy một mảng providers chứa tất cả các lớp service provider sẽ được load. Có một số component có sẵn trong Laravel như mailer, cache, queue sẽ mặc định được thêm sẵn provider trong mảng.

Sau đây, mình sẽ hướng dẫn các bạn tự viết một service provider và đăng ký provider với ứng dụng Laravel.

Tự viết Service Provider

Mọi service provider đều kế thừa từ lớp IlluminateSupportServiceProvider. Mỗi service provider có thể implement 2 phương thức là registerboot. Bạn cũng có thể tạo một provider mới bằng cách sử dụng artisan:

php artisan make:provider NewServiceProvider

register

Trong phương thức register, bạn chỉ nên bind các lớp trong service container. Nếu bạn cố đăng ký event listener, route hay bất kỳ thứ gì khác trong register, bạn có thể gặp lỗi do vô tình sử dụng service có provider chưa được load.

<?phpnamespaceAppProviders;useAppServicesRiakConnection;useIlluminateSupportServiceProvider;classRiakServiceProviderextendsServiceProvider{/**
     * Register any application services.
     *
     * @return void
     */publicfunctionregister(){$this->app->singleton(Connection::class,function($app){returnnewConnection(config('riak'));});}}

Trong ví dụ trên, register trả về một implementation của AppServicesRiakConnection trong service container. Bạn có thể đọc thêm về service container tại đây [https://viblo.asia/p/laravel-8-tim-hieu-ve-service-container-phan-1-bWrZnz0QZxw]

Nếu bạn muốn register nhiều container binding đơn giản, bạn có thể sử dụng thuộc tính bindings và singleton thay vì register từng binding một. Khi provider được load, nó sẽ tự động check 2 thuộc tính này và register các binding.

<?phpnamespaceAppProviders;useAppContractsDowntimeNotifier;useAppContractsServerProvider;useAppServicesDigitalOceanServerProvider;useAppServicesPingdomDowntimeNotifier;useAppServicesServerToolsProvider;useIlluminateSupportServiceProvider;classAppServiceProviderextendsServiceProvider{/**
     * 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

Phương thức boot được gọi sau khi tất cả các service provider khác đã được đăng ký. Dưới đây là một ví dụ đăng ký view composer với boot

<?phpnamespaceAppProviders;useIlluminateSupportFacadesView;useIlluminateSupportServiceProvider;classComposerServiceProviderextendsServiceProvider{/**
     * Bootstrap any application services.
     *
     * @return void
     */publicfunctionboot(){View::composer('view',function(){//});}}

Bạn có thể dùng key của dependency đã được bind trong boot. Trong ví dụ dưới đây, service provider sẽ tự động inject dependency tương ứng với key serialized

useIlluminateContractsRoutingResponseFactory;/**
 * Bootstrap any application services.
 *
 * @param  IlluminateContractsRoutingResponseFactory  $response
 * @return void
 */publicfunctionboot(ResponseFactory$response){$response->macro('serialized',function($value){//});}

Đăng ký provider

Mọi service provider đều được đăng ký trong file config/app.php thông qua mảng providers. Bạn chỉ cần thêm provider của mình vào mảng này.

'providers'=>[// Other Service ProvidersAppProvidersComposerServiceProvider::class,],

Deferred Provider

Deferred provider (provider “chậm”) là provider sẽ chỉ được load khi có request gọi đến service tương ứng. Nếu provider của bạn chỉ đăng ký cho các binding trong service container, việc đăng ký này sẽ bị hoãn cho đến khi một trong số các binding đó thực sự được dùng đến.
Việc hoãn đăng ký này giúp cải thiện performance của ứng dụng, do nó không cần load file trong mọi request.

Laravel compile và lưu các deferred provider cùng với tên lớp service container tương ứng. Chỉ khi bạn resolve service thì Laravel mới load service provider đó.

Để hoãn load một provider, bạn chỉ cần implement interface IlluminateContractsSupportDeferrableProvider và ghi đè phương thức provides. provides trả về các service container bingding được đăng ký bởi provider:

<?phpnamespaceAppProviders;useAppServicesRiakConnection;useIlluminateContractsSupportDeferrableProvider;useIlluminateSupportServiceProvider;classRiakServiceProviderextendsServiceProviderimplementsDeferrableProvider{/**
     * Register any application services.
     *
     * @return void
     */publicfunctionregister(){$this->app->singleton(Connection::class,function($app){returnnewConnection($app['config']['riak']);});}/**
     * Get the services provided by the provider.
     *
     * @return array
     */publicfunctionprovides(){return[Connection::class];}}

Nội dung liên quan

Bạn có thể tìm hiểu thêm các nội dung liên quan (Service Container, Facade) để hiểu rõ hơn về bài viết này.

Tài liệu tham khảo

https://laravel.com/docs/8.x/providers#deferred-providershttps://laracasts.com/series/laravel-6-from-scratch/episodes/41

Nguồn: viblo.asia

Bài viết liên quan

Thay đổi Package Name của Android Studio dể dàng với plugin APR

Nếu bạn đang gặp khó khăn hoặc bế tắc trong việc thay đổi package name trong And

Lỗi không Update Meta_Value Khi thay thế hình ảnh cũ bằng hình ảnh mới trong WordPress

Mã dưới đây hoạt động tốt có 1 lỗi không update được postmeta ” meta_key=

Bài 1 – React Native DevOps các khái niệm và các cài đặt căn bản

Hướng dẫn setup jenkins agent để bắt đầu build mobile bằng jenkins cho devloper an t

Chuyển đổi từ monolith sang microservices qua ví dụ

1. Why microservices? Microservices là kiến trúc hệ thống phần mềm hướng dịch vụ,