サービスプロバイダー
はじめに
サービスプロバイダーは、すべてのLaravelアプリケーションのブートストラップの中心的な場所です。独自のアプリケーションと、Laravelのコアサービスのすべてが、サービスプロバイダーを介してブートストラップされます。
しかし、「ブートストラップ」とはどういう意味でしょうか?一般的には、サービスコンテナへのバインディング、イベントリスナー、ミドルウェア、さらにはルートの登録など、さまざまなものの**登録**を意味します。サービスプロバイダーは、アプリケーションを設定するための中心的な場所です。
Laravelは内部的に数十個のサービスプロバイダーを使用して、メーラー、キュー、キャッシュなどのコアサービスをブートストラップしています。これらのプロバイダーの多くは「遅延」プロバイダーであり、すべてのリクエストでロードされるのではなく、提供するサービスが実際に必要になった場合にのみロードされます。
すべてのユーザー定義サービスプロバイダーは、`bootstrap/providers.php`ファイルに登録されています。次のドキュメントでは、独自のサービスプロバイダーを作成し、Laravelアプリケーションに登録する方法を学習します。
Laravelがリクエストを処理し、内部的にどのように動作するかについてさらに詳しく知りたい場合は、Laravelのリクエストライフサイクルに関するドキュメントをご覧ください。
サービスプロバイダーの作成
すべてのサービスプロバイダーは、`Illuminate\Support\ServiceProvider`クラスを拡張します。ほとんどのサービスプロバイダーには、`register`メソッドと`boot`メソッドが含まれています。`register`メソッド内では、**サービスコンテナにのみバインディングを登録する**必要があります。`register`メソッド内では、イベントリスナー、ルート、その他の機能を登録しようとしてはいけません。
Artisan CLIは、`make:provider`コマンドを使用して新しいプロバイダーを生成できます。Laravelは、新しいプロバイダーをアプリケーションの`bootstrap/providers.php`ファイルに自動的に登録します。
php artisan make:provider RiakServiceProvider
registerメソッド
前述のように、`register`メソッド内では、サービスコンテナにのみバインディングを登録する必要があります。`register`メソッド内では、イベントリスナー、ルート、その他の機能を登録しようとしてはいけません。そうしないと、まだロードされていないサービスプロバイダーが提供するサービスを誤って使用してしまう可能性があります。
基本的なサービスプロバイダーを見てみましょう。サービスプロバイダーのメソッドのいずれかでは、常にサービスコンテナへのアクセスを提供する`$app`プロパティにアクセスできます。
<?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')); }); }}
このサービスプロバイダーは`register`メソッドのみを定義し、そのメソッドを使用してサービスコンテナに`App\Services\Riak\Connection`の実装を定義します。Laravelのサービスコンテナにまだ慣れていない場合は、そのドキュメントをご覧ください。
`bindings`プロパティと`singletons`プロパティ
サービスプロバイダーが多くの単純なバインディングを登録する場合、各コンテナバインディングを手動で登録する代わりに、`bindings`プロパティと`singletons`プロパティを使用することをお勧めします。サービスプロバイダーがフレームワークによってロードされると、これらのプロパティが自動的にチェックされ、それらのバインディングが登録されます。
<?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, ];}
bootメソッド
では、サービスプロバイダー内でビューコンポーザーを登録する必要がある場合はどうすればよいでしょうか?これは`boot`メソッドで行う必要があります。**このメソッドは、他のすべてのサービスプロバイダーが登録された後に呼び出されます**。つまり、フレームワークによって登録された他のすべてのサービスにアクセスできます。
<?php namespace App\Providers; use Illuminate\Support\Facades\View;use Illuminate\Support\ServiceProvider; class ComposerServiceProvider extends ServiceProvider{ /** * Bootstrap any application services. */ public function boot(): void { View::composer('view', function () { // ... }); }}
bootメソッドの依存関係注入
サービスプロバイダーの`boot`メソッドの依存関係を型ヒントで指定できます。サービスコンテナは、必要な依存関係を自動的に注入します。
use Illuminate\Contracts\Routing\ResponseFactory; /** * Bootstrap any application services. */public function boot(ResponseFactory $response): void{ $response->macro('serialized', function (mixed $value) { // ... });}
プロバイダーの登録
すべてのサービスプロバイダーは、`bootstrap/providers.php`設定ファイルに登録されています。このファイルは、アプリケーションのサービスプロバイダーのクラス名を含む配列を返します。
<?php return [ App\Providers\AppServiceProvider::class,];
`make:provider` Artisanコマンドを実行すると、Laravelは生成されたプロバイダーを`bootstrap/providers.php`ファイルに自動的に追加します。ただし、プロバイダークラスを手動で作成した場合は、プロバイダークラスを手動で配列に追加する必要があります。
<?php return [ App\Providers\AppServiceProvider::class, App\Providers\ComposerServiceProvider::class, ];
遅延プロバイダー
サービスコンテナにのみバインディングを登録しているプロバイダーの場合は、登録されたバインディングのいずれかが実際に必要になるまで、その登録を遅らせることができます。このようなプロバイダーのロードを遅延させることで、すべてのリクエストでファイルシステムからロードされないため、アプリケーションのパフォーマンスが向上します。
Laravelは、遅延サービスプロバイダーによって提供されるすべてのサービスのリストとそのサービスプロバイダークラス名をコンパイルして格納します。その後、これらのサービスのいずれかを解決しようとすると、Laravelはサービスプロバイダーをロードします。
プロバイダーのロードを遅延させるには、`\Illuminate\Contracts\Support\DeferrableProvider`インターフェースを実装し、`provides`メソッドを定義します。`provides`メソッドは、プロバイダーによって登録されたサービスコンテナバインディングを返す必要があります。
<?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{ /** * Register any application services. */ public function register(): void { $this->app->singleton(Connection::class, function (Application $app) { return new Connection($app['config']['riak']); }); } /** * Get the services provided by the provider. * * @return array<int, string> */ public function provides(): array { return [Connection::class]; }}