はじめに
サービスプロバイダーは、すべての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
メソッド内でイベントリスナー、ルート、または他の機能を登録しようとするべきではありません。そうしないと、まだロードされていないサービスプロバイダーによって提供されるサービスを誤って使用する可能性があります。
基本的なサービスプロバイダーを見てみましょう。任意のサービスプロバイダーのメソッド内では、サービスコンテナへのアクセスを提供する$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
プロパティを使用することを検討するかもしれません。サービスプロバイダーがフレームワークによってロードされると、これらのプロパティを自動的にチェックし、そのバインディングを登録します:
<?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
メソッド内で行うべきです。このメソッドは、すべての他のサービスプロバイダーが登録された後に呼び出されます。つまり、フレームワークによって登録された他のすべてのサービスにアクセスできます:
<?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
メソッドに依存性をタイプヒントすることができます。サービスコンテナは、必要な依存性を自動的に注入します:
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,
];
遅延プロバイダー
プロバイダーがのみサービスコンテナにバインディングを登録している場合、登録されたバインディングの1つが実際に必要になるまで、その登録を遅延させることを選択できます。このようなプロバイダーのロードを遅延させることで、アプリケーションのパフォーマンスが向上します。なぜなら、毎回リクエストのたびにファイルシステムからロードされないからです。
Laravelは、遅延サービスプロバイダーによって提供されるすべてのサービスのリストをコンパイルし、そのサービスプロバイダーのクラス名とともに保存します。そして、これらのサービスの1つを解決しようとしたときにのみ、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];
}
}