Service Providers
Table of Contents
Introduction
Service providers は、すべての Laravel application のブートストラッピングの中心的な場所です。あなた自身の application 、そして Laravel のすべてのコア services も、 service providers を通じてブートストラップされます。
しかし、"bootstrapped" とは何を意味するのでしょうか?一般的には、 service container のバインディング、 event listeners 、 middleware 、さらには routes を含むモノを登録することを意味します。 Service providers は、 application を設定するための中心的な場所です。
Laravel は、 mailer 、 queue 、 cache などのコア services をブートストラップするために、内部で数十の service providers を使用します。これらの providers の多くは deferred providers であり、すべての request でロードされるわけではなく、提供する services が実際に必要とされるときだけロードされます。
すべてのユーザー定義の service providers はbootstrap/providers.php
ファイルに登録されています。以下のドキュメンテーションでは、独自の service providers の作成方法とそれらを Laravel application に register する方法を学びます。
NOTE
もし、 Laravel がリクエストをどのように処理し、内部でどのように動作するかについて詳しく学びたい場合は、 Laravel の request ライフサイクルに関するドキュメンテーションをご覧ください。
Writing Service Providers
すべての service providers はIlluminate\Support\ServiceProvider
class を拡張します。ほとんどの service providers にはregister
とboot
の method が含まれています。register
method 内で、service containerにバインドするものだけを記述するべきです。register
method 内で event listeners、routes、または他の機能を登録しようとすることは絶対にしてはなりません。
Artisan CLI は make:provider
command を用いて新しい provider を生成することができます。 Laravel は自動的にあなたの新しい provider をアプリケーションの bootstrap/providers.php
ファイルに register します:
php artisan make:provider RiakServiceProvider
Register Method
前述の通り、register
の method 内では、service containerに対してバインドすることだけを行うべきです。event listeners、routes、または register
の method 内の他の機能を登録しようと試みるべきではありません。そうすると、まだロードされていない service provider によって提供される service を誤って使用する可能性があります。
基本的な service provider を見てみましょう。 service provider のメソッド内では、$app
プロパティへのアクセスが常に可能で、これにより service container へのアクセスが可能になります:
<?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'));
});
}
}
この service provider は、register
method だけを定義し、その method を使用してApp\Services\Riak\Connection
の実装を service container 内で定義します。まだ Laravel の service container についてよく知らないのであれば、そのドキュメンテーションをご覧ください。
bindings
と singletons
プロパティ
あなたの service provider が多くのシンプルなバインディングを登録する場合、各コンテナバインディングを手動で登録する代わりに bindings
および singletons
プロパティを使用することを希望するかもしれません。 service provider がフレームワークによって読み込まれると、それは自動的にこれらのプロパティを確認し、そのバインディングを 登録します。
<?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 Method とは
それでは、私たちの service providers の中でview コンポーザーを登録する必要がある場合はどうするべきでしょうか? これは boot
method 内で行われるべきです。この method は、他のすべての service providers が登録された後に呼び出されます、つまり、フレームワークが登録した他のすべての services にアクセスできるということです:
<?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 Method Dependency Injection
あなたの service プロバイダのboot
method に依存関係を types ヒントすることができます。service containerは、必要な依存関係を自動的に挿入します:
use Illuminate\Contracts\Routing\ResponseFactory;
/**
* Bootstrap any application services.
*/
public function boot(ResponseFactory $response): void
{
$response->macro('serialized', function (mixed $value) {
// ...
});
}
Registering Providers
すべての service providers は、bootstrap/providers.php
設定ファイルに登録されています。このファイルはあなたの application の service providers の class 名を含む array を返します:
<?php
// This file is automatically generated by Laravel...
return [
App\Providers\AppServiceProvider::class,
];
make:provider
の Artisan command を呼び出すと、Laravel は自動的に生成されたプロバイダをbootstrap/providers.php
ファイルに追加します。ただし、プロバイダ class を手動で作成した場合は、プロバイダ class を array に手動で追加する必要があります。
<?php
// This file is automatically generated by Laravel...
return [
App\Providers\AppServiceProvider::class,
App\Providers\ComposerServiceProvider::class, // [tl! add]
];
Deferred Providers
あなたの provider がservice containerにのみバインディングを登録している場合、登録されたバインディングのうちの 1 つが実際に必要になるまでその登録を延期することを選択できます。このような provider の読み込みを遅らせると、毎回の request でファイルシステムからロードされないため、 application のパフォーマンスが向上します。
Laravel は、遅延された service providers によって提供されるすべての services のリストをコンパイルし保存し、その service providers ー class の名前とともに保存します。そして、これらの services の一つを解決しようとするときだけ、Laravel は service providers をロードします。
provider の読み込みを遅延するには、\Illuminate\Contracts\Support\DeferrableProvider
インターフェースを実装し、provides
method を定義します。 provides
method は、 provider によって登録された service container のバインディングを返すべきです。
<?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];
}
}