このページはパッケージ開発の基礎の知識を前提としています。サービスプロバイダーの基本的な仕組みを理解してから読むことをおすすめします。
なぜ遅延プロバイダーが必要か
通常のサービスプロバイダーはすべてのリクエストでregister() と boot() が呼ばれます。メール送信、キュー、キャッシュなど、すべてのページで使わない機能まで毎回初期化するのは無駄です。
DeferrableProvider インターフェース
Illuminate\Contracts\Support\DeferrableProvider は provides() メソッドひとつを持つシンプルなインターフェースです。
基本的な実装
遅延プロバイダーの実装は3ステップです。1
DeferrableProvider を implements する
2
register() でサービスをバインドする
通常のプロバイダーと同様に
register() にバインドを記述します。3
provides() で登録したサービスを返す
provides() は register() でバインドしたすべてのサービスを返す必要があります。Laravelはこのリストを元に「どのサービスを要求したときにこのプロバイダーを読み込むか」を判断します。サービスマニフェストの仕組み
Laravel は起動時にbootstrap/cache/services.php というマニフェストファイルを生成します。このファイルに遅延プロバイダーが提供するサービスの一覧が保存されています。
内部動作のフロー
provides() メソッドの重要性
provides() に登録漏れがあると、そのサービスは永遠に解決されません。
$bindings / $singletons プロパティを使っている場合も同様に provides() に含めます。
遅延プロバイダーの制約
遅延プロバイダーはコンテナへのバインディング登録だけを目的としたプロバイダーに向いています。以下のようなことをboot() で行うプロバイダーは遅延にできません。
when() メソッド — イベントトリガーによる登録
when() メソッドを使うと、特定のイベントが発火したときにプロバイダーを登録できます。これは、ジョブ処理系など特定のコンテキストでのみ必要なプロバイダーに使えます。
when() に返したイベントが発火すると、サービスが直接解決されていなくてもプロバイダーが読み込まれます。
パッケージ開発での活用
サードパーティパッケージとして配布するときも、遅延プロバイダーはユーザーのアプリケーションのパフォーマンスに貢献します。推奨パターン
mergeConfigFrom() は設定のキャッシュ有無を内部でチェックしているため、遅延プロバイダーの register() の中で呼んでも安全です。ただし設定がキャッシュ済みの場合は何もしません。runningInConsole() で Artisan コマンド登録を分離する
コマンド登録は Artisan 起動時のみ必要なので、runningInConsole() で条件分岐します。ただしコマンドを提供するプロバイダーを遅延にする場合は、コマンドクラスも provides() に含めるか、コマンド専用のプロバイダーを別に用意してください。
Laravel コアでの使用例
Laravelのコアプロバイダーの多くは遅延プロバイダーです。毎リクエストで使わないサービスをすべて即時読み込みしないための設計です。
API エンドポイントのみのアプリケーションでは、
MailServiceProvider や BroadcastServiceProvider がリクエスト中に一度も読み込まれないこともあります。
遅延化すべきかの判断基準
遅延化に向いているサービス
遅延化に向いているサービス
- すべてのリクエストで使われるわけではないサービス(メール、レポート、外部 API クライアントなど)
- 初期化に外部接続やファイル読み込みが必要なサービス
- 重いオブジェクトグラフを持つサービス
- CLI でのみ使うコマンドを提供するプロバイダー
遅延化に向いていないサービス
遅延化に向いていないサービス
- ルートを登録するプロバイダー(
loadRoutesFromなど) - 常時機能するミドルウェアや例外ハンドラーを登録するプロバイダー
- Eloquent のグローバルスコープやオブザーバーを登録するプロバイダー
- リクエストの大半で使われる軽量なサービス(遅延のオーバーヘッドの方が大きくなる場合)
関連ページ
パッケージ開発の基礎
サービスプロバイダーを核としたLaravelパッケージの開発方法を解説します。
パッケージのバージョン互換性管理
LaravelとPHPのメジャーバージョンアップに対応するパッケージのメンテナンス戦略を解説します。