跳到內容

服務提供者

簡介

服務提供者是所有 Laravel 應用程式啟動的核心位置。您自己的應用程式以及 Laravel 的所有核心服務,都是透過服務提供者啟動的。

但是,「啟動」是什麼意思呢? 一般來說,我們指的是註冊事物,包括註冊服務容器綁定、事件監聽器、中介層,甚至路由。 服務提供者是設定應用程式的核心位置。

Laravel 在內部使用數十個服務提供者來啟動其核心服務,例如郵件程式、佇列、快取等。 這些提供者中有許多是「延遲」提供者,這表示它們不會在每個請求上載入,而只會在實際需要它們提供的服務時載入。

所有使用者定義的服務提供者都在 bootstrap/providers.php 檔案中註冊。 在以下文件中,您將學習如何編寫自己的服務提供者並將其註冊到您的 Laravel 應用程式中。

如果您想了解更多關於 Laravel 如何處理請求以及內部運作方式,請查看我們關於 Laravel 請求生命週期的文件。

撰寫服務提供者

所有服務提供者都擴展了 Illuminate\Support\ServiceProvider 類別。 大多數服務提供者都包含 registerboot 方法。 在 register 方法中,您應該僅將事物綁定到服務容器中。 您絕不應嘗試在 register 方法中註冊任何事件監聽器、路由或任何其他功能。

Artisan CLI 可以透過 make:provider 命令產生新的提供者。 Laravel 將自動在應用程式的 bootstrap/providers.php 檔案中註冊您的新提供者

1php artisan make:provider RiakServiceProvider

Register 方法

如前所述,在 register 方法中,您應該僅將事物綁定到 服務容器 中。 您絕不應嘗試在 register 方法中註冊任何事件監聽器、路由或任何其他功能。 否則,您可能會意外使用由尚未載入的服務提供者提供的服務。

讓我們看看一個基本的服務提供者。 在您的任何服務提供者方法中,您始終可以存取 $app 屬性,該屬性提供對服務容器的存取權

1<?php
2 
3namespace App\Providers;
4 
5use App\Services\Riak\Connection;
6use Illuminate\Contracts\Foundation\Application;
7use Illuminate\Support\ServiceProvider;
8 
9class RiakServiceProvider extends ServiceProvider
10{
11 /**
12 * Register any application services.
13 */
14 public function register(): void
15 {
16 $this->app->singleton(Connection::class, function (Application $app) {
17 return new Connection(config('riak'));
18 });
19 }
20}

此服務提供者僅定義了一個 register 方法,並使用該方法在服務容器中定義了 App\Services\Riak\Connection 的實作。 如果您還不熟悉 Laravel 的服務容器,請查看其文件

bindingssingletons 屬性

如果您的服務提供者註冊了許多簡單的綁定,您可能希望使用 bindingssingletons 屬性,而不是手動註冊每個容器綁定。 當框架載入服務提供者時,它將自動檢查這些屬性並註冊它們的綁定

1<?php
2 
3namespace App\Providers;
4 
5use App\Contracts\DowntimeNotifier;
6use App\Contracts\ServerProvider;
7use App\Services\DigitalOceanServerProvider;
8use App\Services\PingdomDowntimeNotifier;
9use App\Services\ServerToolsProvider;
10use Illuminate\Support\ServiceProvider;
11 
12class AppServiceProvider extends ServiceProvider
13{
14 /**
15 * All of the container bindings that should be registered.
16 *
17 * @var array
18 */
19 public $bindings = [
20 ServerProvider::class => DigitalOceanServerProvider::class,
21 ];
22 
23 /**
24 * All of the container singletons that should be registered.
25 *
26 * @var array
27 */
28 public $singletons = [
29 DowntimeNotifier::class => PingdomDowntimeNotifier::class,
30 ServerProvider::class => ServerToolsProvider::class,
31 ];
32}

Boot 方法

那麼,如果我們需要在服務提供者中註冊視圖組合器怎麼辦? 這應該在 boot 方法中完成。 此方法在所有其他服務提供者都已註冊後呼叫,這表示您可以存取框架已註冊的所有其他服務

1<?php
2 
3namespace App\Providers;
4 
5use Illuminate\Support\Facades\View;
6use Illuminate\Support\ServiceProvider;
7 
8class ComposerServiceProvider extends ServiceProvider
9{
10 /**
11 * Bootstrap any application services.
12 */
13 public function boot(): void
14 {
15 View::composer('view', function () {
16 // ...
17 });
18 }
19}

Boot 方法依賴注入

您可以為服務提供者的 boot 方法輸入提示相依性。 服務容器將自動注入您需要的任何相依性

1use Illuminate\Contracts\Routing\ResponseFactory;
2 
3/**
4 * Bootstrap any application services.
5 */
6public function boot(ResponseFactory $response): void
7{
8 $response->macro('serialized', function (mixed $value) {
9 // ...
10 });
11}

註冊提供者

所有服務提供者都在 bootstrap/providers.php 設定檔中註冊。 此檔案傳回一個陣列,其中包含應用程式服務提供者的類別名稱

1<?php
2 
3return [
4 App\Providers\AppServiceProvider::class,
5];

當您調用 make:provider Artisan 命令時,Laravel 將自動將產生的提供者新增至 bootstrap/providers.php 檔案。 但是,如果您是手動建立提供者類別,則應手動將提供者類別新增至陣列

1<?php
2 
3return [
4 App\Providers\AppServiceProvider::class,
5 App\Providers\ComposerServiceProvider::class,
6];

延遲提供者

如果您的提供者服務容器中註冊綁定,您可以選擇延遲其註冊,直到實際需要其中一個已註冊的綁定。 延遲載入此類提供者將提高應用程式的效能,因為它不會在每個請求上從檔案系統載入。

Laravel 編譯並儲存延遲服務提供者提供的所有服務的清單,以及其服務提供者類別的名稱。 然後,只有當您嘗試解析這些服務之一時,Laravel 才會載入服務提供者。

若要延遲載入提供者,請實作 \Illuminate\Contracts\Support\DeferrableProvider 介面並定義 provides 方法。 provides 方法應傳回提供者註冊的服務容器綁定

1<?php
2 
3namespace App\Providers;
4 
5use App\Services\Riak\Connection;
6use Illuminate\Contracts\Foundation\Application;
7use Illuminate\Contracts\Support\DeferrableProvider;
8use Illuminate\Support\ServiceProvider;
9 
10class RiakServiceProvider extends ServiceProvider implements DeferrableProvider
11{
12 /**
13 * Register any application services.
14 */
15 public function register(): void
16 {
17 $this->app->singleton(Connection::class, function (Application $app) {
18 return new Connection($app['config']['riak']);
19 });
20 }
21 
22 /**
23 * Get the services provided by the provider.
24 *
25 * @return array<int, string>
26 */
27 public function provides(): array
28 {
29 return [Connection::class];
30 }
31}