Service providers
公式ドキュメント
概要
Laravelアプリケーションのbootstrapに責任を持つ
Service providersによって、すべての
Laravelのコアサービスと自作のアプリケーションがbootstrapされる
bootstrapとは、次のようなものをregisterすること
sercive container binding
event listener
middleware
router
LaravelにはどんなService Providerがロードされるのか
config/app.php
の
providers
arrayに自作アプリケーションでロードするservice provideの
リストがあるその多くが deferred
なproviderで、すべてのリクエストで毎回ロードされるわけではなく、必要なときのみロードされる。
自作のService Providersを書く
ServiceProviderクラスを書く
Illuminate\Support\ServiceProvider
を継承し register()
と boot()
をもつ
Service Providerのメソッドの呼ばれる順序
1. 全Providerの register()
2. 全Providerの boot()
この順序が担保されているため、bootの中では $app
が使える
$app
はほかのService ProviderでbindingがすんだService containerが利用できるオブジェクト
register()
インタフェースにインスタンスをbindするのが典型的な使い方

注意:それ以外のいかなるevent listenerやroutesや機能の一部をかいてはいけない
まだロードしていないサービスを意図せずService Providerから使うことを防ぐため
boot()
> This method is called after all other service providers have been registered, meaning you have access to all other services that have been registered by the framework:
phppublic function boot(ResponseFactory $response)
{
$response->macro('caps', function ($value) {
//
});
}
bindingsとsingletons
service providerで単純なbindingをたくさんregisterするときに便利な機能
service providerがロードされる時点でプロパティがチェックされて結合を登録する
使わない場合
php$this->app->bind(
ServerProvider::class, // インタフェース
DigitalOceanServerProvider::class //実装クラス
);
使う場合
phpclass AppServiceProvider extends ServiceProvider
{
/**
* 登録する必要のある全コンテナbinding
*
* @var array
*/
public $bindings = [
ServerProvider::class => DigitalOceanServerProvider::class,
];
サービスプロバイダを登録する
Service Providerを書きおわったら、 config/app.php
に登録する
プロバイダを追加する際にはこの配列に追加する
1. deferredServices
配列にdifferedされるServiceProviesを登録する
たぶんこれが
bootstrapPath().'/cache/services.php
に保存される

2. differedなサービスプロバイダを初期化する
\Illuminate\Foundation\Bootstrap\RegisterProviders
を含む
$bootstrappers
に登録されたbootstrap classが上から順に実行される
getCachedServicesPath()
が返す実態は $this->bootstrapPath().'/cache/services.php'
このファイルには providers
や deferred
などの配列が定義されている
services.php<?php return array (
'providers' => array (
0 => 'Illuminate\\Auth\\AuthServiceProvider',
1 => 'Illuminate\\Broadcasting\\BroadcastServiceProvider',
2 => 'Illuminate\\Bus\\BusServiceProvider',
// 省略
),
'deferred' => array (
'Illuminate\\Broadcasting\\BroadcastManager' => 'Illuminate\\Broadcasting\\BroadcastServiceProvider',
// 省略
),
ここまではアプリケーションの初期化プロセスで行われる。まだ実態は作られていないことに注意
実際に使うときがくると、
Illuminate\Foundation\Application->loadDeferredProvider()
から
registerDeferredProvider()
が
呼ばれ、前記services.phpで定義されている
deferred
なServiceProviders(BroadcastManagerとか)が初期化される
各Service Providerのregister()やboot()が呼ばれて、インタフェースに対する具象クラスを作成する
これはどこかから呼ばれる?
$bootstrappers
の
最後に
Illuminate\Foundation\Bootstrap\BootProviders
の
bootstrap()
が
呼び出されることで
Illuminate\Contracts\Foundation\Application->boot()
が呼び出される
各ServiceProviderの boot()
メソッドが順次呼び出される
Deferred Provider
Laravelはdefferedなサービスプロバイダによって提供されるサービスの一覧をコンパイルして、サービスプロバイダの名前とともに保存している。実際にサービスのうちの一つが必要になったときに、サービスプロバイダをロードする