サービスプロバイダ
イントロダクション
サービスプロバイダは、すべてのLaravelアプリケーションの起動処理の中心となる場所です。あなた自身のアプリケーションだけでなく、Laravelのすべてのコアサービスもサービスプロバイダを介して起動されます。
しかし、「起動(bootstrapped)」とはどういう意味でしょうか?一般的には、サービスコンテナへの結合、イベントリスナ、ミドルウェア、さらにはルートの登録など、物事を登録することを意味します。サービスプロバイダは、アプリケーションを設定するための中核となる場所です。
Laravelは内部で数十のサービスプロバイダを使用して、メーラー、キュー、キャッシュなどのコアサービスを起動します。これらのプロバイダの多くは「遅延」プロバイダであり、リクエストごとにロードされるのではなく、それらが提供するサービスが実際に必要になったときにのみロードされることを意味します。
ユーザー定義のサービスプロバイダはすべて、bootstrap/providers.phpファイルで登録します。以下のドキュメントでは、独自のサービスプロバイダを作成し、Laravelアプリケーションに登録する方法を学びます。
Laravelがリクエストをどのように処理し、内部でどのように動作するかについて詳しく知りたい場合は、Laravelのリクエストライフサイクルに関するドキュメントを確認してください。
サービスプロバイダの作成
すべてのサービスプロバイダはIlluminate\Support\ServiceProviderクラスを拡張します。ほとんどのサービスプロバイダには、registerとbootメソッドが含まれています。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 ServiceProvider10{11 /**12 * Register any application services.13 */14 public function register(): void15 {16 $this->app->singleton(Connection::class, function (Application $app) {17 return new Connection(config('riak'));18 });19 }20}
このサービスプロバイダはregisterメソッドのみを定義しており、そのメソッドを使用してサービスコンテナにApp\Services\Riak\Connectionの実装を定義しています。Laravelのサービスコンテナにまだ慣れていない場合は、そのドキュメントを確認してください。
bindingsプロパティとsingletonsプロパティ
サービスプロバイダが多くの単純な結合を登録する場合、各コンテナ結合を手動で登録する代わりに、bindingsプロパティとsingletonsプロパティを使用することもできます。サービスプロバイダがフレームワークによってロードされると、自動的にこれらのプロパティをチェックし、それらの結合を登録します。
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 ServiceProvider13{14 /**15 * All of the container bindings that should be registered.16 *17 * @var array18 */19 public $bindings = [20 ServerProvider::class => DigitalOceanServerProvider::class,21 ];22 23 /**24 * All of the container singletons that should be registered.25 *26 * @var array27 */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(): void14 {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<?php2 3return [4 App\Providers\AppServiceProvider::class,5];
Artisanコマンドのmake:providerを実行すると、Laravelは生成されたプロバイダをbootstrap/providers.phpファイルに自動的に追加します。しかし、プロバイダクラスを手動で作成した場合は、そのプロバイダクラスを配列に手動で追加する必要があります。
1<?php2 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 DeferrableProvider11{12 /**13 * Register any application services.14 */15 public function register(): void16 {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(): array28 {29 return [Connection::class];30 }31}