はじめに

サービスプロバイダーは、すべてのLaravelアプリケーションのブートストラップの中心的な場所です。あなた自身のアプリケーションと、Laravelのコアサービスはすべてサービスプロバイダーを介してブートストラップされます。

しかし、「ブートストラップ」とは何を意味するのでしょうか?一般的には、登録することを意味します。これには、サービスコンテナのバインディング、イベントリスナー、ミドルウェア、さらにはルートの登録が含まれます。サービスプロバイダーは、アプリケーションを構成するための中心的な場所です。

Laravelは、メール送信、キュー、キャッシュなどのコアサービスをブートストラップするために、内部で数十のサービスプロバイダーを使用しています。これらのプロバイダーの多くは「遅延」プロバイダーであり、これは、提供されるサービスが実際に必要なときにのみロードされることを意味します。

すべてのユーザー定義のサービスプロバイダーは、bootstrap/providers.phpファイルに登録されます。次のドキュメントでは、独自のサービスプロバイダーを作成し、それをLaravelアプリケーションに登録する方法を学びます。

Laravelがリクエストを処理し、内部でどのように機能するかについてもっと知りたい場合は、Laravelのリクエストライフサイクルに関するドキュメントを確認してください。

サービスプロバイダーの作成

すべてのサービスプロバイダーは、Illuminate\Support\ServiceProviderクラスを拡張します。ほとんどのサービスプロバイダーには、registerメソッドとbootメソッドが含まれています。registerメソッド内では、サービスコンテナにのみバインディングを行うべきです。registerメソッド内でイベントリスナー、ルート、または他の機能を登録しようとするべきではありません。

Artisan CLIは、make:providerコマンドを介して新しいプロバイダーを生成できます。Laravelは、自動的に新しいプロバイダーをアプリケーションのbootstrap/providers.phpファイルに登録します:

  1. php artisan make:provider RiakServiceProvider

登録メソッド

前述のように、registerメソッド内では、サービスコンテナにのみバインディングを行うべきです。registerメソッド内でイベントリスナー、ルート、または他の機能を登録しようとするべきではありません。そうしないと、まだロードされていないサービスプロバイダーによって提供されるサービスを誤って使用する可能性があります。

基本的なサービスプロバイダーを見てみましょう。任意のサービスプロバイダーのメソッド内では、サービスコンテナへのアクセスを提供する$appプロパティに常にアクセスできます:

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

このサービスプロバイダーはregisterメソッドのみを定義し、そのメソッドを使用してサービスコンテナ内のApp\Services\Riak\Connectionの実装を定義します。Laravelのサービスコンテナにまだ慣れていない場合は、そのドキュメントを確認してください。

バインディングとシングルトンプロパティ

サービスプロバイダーが多くのシンプルなバインディングを登録する場合、各コンテナバインディングを手動で登録する代わりに、bindingsおよびsingletonsプロパティを使用することを検討するかもしれません。サービスプロバイダーがフレームワークによってロードされると、これらのプロパティを自動的にチェックし、そのバインディングを登録します:

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

ブートメソッド

では、サービスプロバイダー内でビューコンポーザーを登録する必要がある場合はどうすればよいでしょうか?これはbootメソッド内で行うべきです。このメソッドは、すべての他のサービスプロバイダーが登録された後に呼び出されます。つまり、フレームワークによって登録された他のすべてのサービスにアクセスできます:

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

ブートメソッドの依存性注入

サービスプロバイダーのbootメソッドに依存性をタイプヒントすることができます。サービスコンテナは、必要な依存性を自動的に注入します:

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

プロバイダーの登録

すべてのサービスプロバイダーは、bootstrap/providers.php設定ファイルに登録されます。このファイルは、アプリケーションのサービスプロバイダーのクラス名を含む配列を返します:

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

make:provider Artisanコマンドを呼び出すと、Laravelは自動的に生成されたプロバイダーをbootstrap/providers.phpファイルに追加します。ただし、プロバイダークラスを手動で作成した場合は、プロバイダークラスを配列に手動で追加する必要があります:

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

遅延プロバイダー

プロバイダーがのみサービスコンテナにバインディングを登録している場合、登録されたバインディングの1つが実際に必要になるまで、その登録を遅延させることを選択できます。このようなプロバイダーのロードを遅延させることで、アプリケーションのパフォーマンスが向上します。なぜなら、毎回リクエストのたびにファイルシステムからロードされないからです。

Laravelは、遅延サービスプロバイダーによって提供されるすべてのサービスのリストをコンパイルし、そのサービスプロバイダーのクラス名とともに保存します。そして、これらのサービスの1つを解決しようとしたときにのみ、Laravelはサービスプロバイダーをロードします。

プロバイダーのロードを遅延させるには、\Illuminate\Contracts\Support\DeferrableProviderインターフェースを実装し、providesメソッドを定義します。providesメソッドは、プロバイダーによって登録されたサービスコンテナのバインディングを返す必要があります:

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