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

WebP là gì? Hướng dẫn cách để chuyển hình ảnh jpg, png qua webp

WebP là gì? WebP là một định dạng ảnh hiện đại, được phát triển bởi Google

Điểm khác biệt giữa IPv4 và IPv6 là gì?

IPv4 và IPv6 là hai phiên bản của hệ thống địa chỉ Giao thức Internet (IP). IP l

Check nameservers của tên miền xem website trỏ đúng chưa

Tìm hiểu cách check nameservers của tên miền để xác định tên miền đó đang dùn

Mình đang dùng Google Domains để check tên miền hàng ngày

Từ khi thông báo dịch vụ Google Domains bỏ mác Beta, mình mới để ý và bắt đầ