一、Laravel服務(wù)提供者介紹
服務(wù)提供者是所有 Laravel 應(yīng)用的引導(dǎo)中心。你的應(yīng)用,以及所有 Laravel 核心服務(wù),都是通過服務(wù)提供者引導(dǎo)的。
但是,「引導(dǎo)」是什么意思呢?通常,我們可以理解為注冊(cè),比如注冊(cè)服務(wù)容器綁定,事件監(jiān)聽器,中間件,甚至是路由。服務(wù)提供者是配置應(yīng)用程序的中心。
Laravel 在其內(nèi)部使用多個(gè)服務(wù)提供者引導(dǎo)其核心服務(wù),比如郵件、隊(duì)列、緩存等。許多服務(wù)提供者是延遲加載的,也就是說他們不會(huì)在每次請(qǐng)求時(shí)都加載,只有他們的服務(wù)實(shí)際被需要時(shí)才會(huì)加載。
所有用戶定義的服務(wù)提供者都在 bootstrap/providers.php 文件中注冊(cè)。在以下文檔中,將學(xué)習(xí)如何編寫自己的服務(wù)提供商,并將其注冊(cè)到 Laravel 應(yīng)用中。
二、編寫服務(wù)提供者
所有的服務(wù)提供者都繼承了 Illuminate\Support\ServiceProvider 類。大部分服務(wù)提供者都包含一個(gè) register 方法和一個(gè) boot 方法。 在 register 方法中,你只應(yīng)將服務(wù)綁定到服務(wù)容器。而不要嘗試在 register 方法中注冊(cè)任何監(jiān)聽器,路由,或者其他任何功能。
使用 Artisan 命令行工具的 make:provider 命令可以生成新的服務(wù)提供者類。Laravel 將會(huì)在應(yīng)用的 bootstrap/providers.php 文件中自動(dòng)注冊(cè)你新增的服務(wù)提供者:
php artisan make:provider RiakServiceProvider
1、Register 方法
如前所述,在 register 方法中,你只應(yīng)將服務(wù)綁定到服務(wù)容器。而不應(yīng)該在 register 方法中嘗試注冊(cè)任何事件監(jiān)聽器、路由或者任何其他功能。否則,你可能意外地調(diào)用服務(wù)提供者尚未加載的服務(wù)。
讓我們來看一個(gè)基礎(chǔ)的服務(wù)提供者。在任何服務(wù)提供者方法中,你總是通過 $app 屬性來訪問服務(wù)容器:
<?php namespace App\Providers; use App\Services\Riak\Connection; use Illuminate\Contracts\Foundation\Application; use Illuminate\Support\ServiceProvider; class RiakServiceProvider extends ServiceProvider { /** * Register any application services. */ public function register(): void { $this->app->singleton(Connection::class, function (Application $app) { return new Connection(config('riak')); }); } }
該服務(wù)提供者只定義了一個(gè) reigister 方法,并使用該方法在服務(wù)容器中定義了 App\Services\Riak\Connection 的一個(gè)實(shí)現(xiàn)。如果你還不熟悉 Laravel 的服務(wù)容器,請(qǐng)查看其文檔。
bindings 和 singletons 屬性
如果你的服務(wù)提供者注冊(cè)了許多簡單的綁定,你可能想用 bindings 和 singletons 屬性而不是手動(dòng)注冊(cè)每個(gè)容器綁定。當(dāng)框架加載服務(wù)提供者時(shí),它會(huì)自動(dòng)檢測(cè)這些屬性并注冊(cè)其綁定:
<?php namespace App\Providers; use App\Contracts\DowntimeNotifier; use App\Contracts\ServerProvider; use App\Services\DigitalOceanServerProvider; use App\Services\PingdomDowntimeNotifier; use App\Services\ServerToolsProvider; use Illuminate\Support\ServiceProvider; 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, ]; }
2、啟動(dòng)方法
如果我們需要在服務(wù)提供者中注冊(cè)視圖組合器,應(yīng)該在 boot 方法中完成。這個(gè)方法在所有其他服務(wù)提供者注冊(cè)之后調(diào)用,這意味著你可以訪問框架注冊(cè)的所有其他服務(wù):
<?php namespace App\Providers; use Illuminate\Support\Facades\View; use Illuminate\Support\ServiceProvider; class ComposerServiceProvider extends ServiceProvider { /** * 啟動(dòng)任何應(yīng)用服務(wù)。 */ public function boot(): void { View::composer('view', function () { // ... }); } }
3、啟動(dòng)方法的依賴注入
你可以為服務(wù)提供者的 boot 方法類型提示依賴。服務(wù)容器將自動(dòng)注入你需要的任何依賴項(xiàng):
use Illuminate\Contracts\Routing\ResponseFactory; /** * 啟動(dòng)任何應(yīng)用服務(wù)。 */ public function boot(ResponseFactory $response): void { $response->macro('serialized', function (mixed $value) { // ... }); }
三、注冊(cè)服務(wù)提供者
所有服務(wù)提供者都在 bootstrap/providers.php 配置文件中注冊(cè)。這個(gè)文件返回一個(gè)包含你的應(yīng)用服務(wù)提供者類名的數(shù)組:
<?php return [ App\Providers\AppServiceProvider::class, ];
當(dāng)你調(diào)用 make:provider Artisan 命令時(shí),Laravel 將自動(dòng)將生成的提供者添加到 bootstrap/providers.php 文件中。然而,如果你手動(dòng)創(chuàng)建了提供者類,你應(yīng)該手動(dòng)將提供者類添加到數(shù)組中:
<?php return [ App\Providers\AppServiceProvider::class, App\Providers\ComposerServiceProvider::class, // [tl! add] ];
四、延遲提供者
如果你的提供者僅在服務(wù)容器中注冊(cè)綁定,你可以選擇延遲其注冊(cè),直到實(shí)際需要注冊(cè)的綁定之一。延遲加載這樣的提供者將提高你的應(yīng)用性能,因?yàn)樗粫?huì)在每個(gè)請(qǐng)求上從文件系統(tǒng)加載。
Laravel 編譯并存儲(chǔ)由延時(shí)服務(wù)提供者提供的所有服務(wù)的列表,以及其服務(wù)提供商類的名稱。然后,只有當(dāng)你嘗試解析其中一個(gè)服務(wù)時(shí),Laravel 才會(huì)加載服務(wù)提供商。
要延時(shí)加載提供商,請(qǐng)實(shí)現(xiàn) \Illuminate\Contracts\Support\DeferrableProvider 接口并定義 provides 方法。provides 方法應(yīng)返回由提供商注冊(cè)的服務(wù)容器綁定:
<?php namespace App\Providers; use App\Services\Riak\Connection; use Illuminate\Contracts\Foundation\Application; use Illuminate\Contracts\Support\DeferrableProvider; use Illuminate\Support\ServiceProvider; class RiakServiceProvider extends ServiceProvider implements DeferrableProvider { /** * 注冊(cè)任何應(yīng)用服務(wù) */ public function register(): void { $this->app->singleton(Connection::class, function (Application $app) { return new Connection($app['config']['riak']); }); } /** * 獲取服務(wù)提供者 * * @return array<int, string> */ public function provides(): array { return [Connection::class]; } }
————————————————
原文作者:Laravel China 社區(qū)文檔:《Laravel 11 中文文檔(11.x)》
轉(zhuǎn)自鏈接:https://learnku.com/docs/laravel/11.x/providersmd/16655