はじめに
前回のライフサイクル編の続きとして、今回はサービスコンテナのご紹介をします。
シリーズ
- Laravelの構成概念 第1回 ライフサイクル編
- Laravelの構成概念 第2回 サービスコンテナ編
- Laravelの構成概念 第3回 サービスプロバイダ編(近日公開)
環境
- Laravel 8.5.11
公式ドキュメント
用語
Laravel サービスコンテナ
クラスの依存関係を管理し、依存注入(DI)を実行するための機能です。
- サービスコンテナにクラスを登録する(結合)
- サービスコンテナに登録されたクラスのインスタンスを取り出す(依存解決)
サービスコンテナはサービス(クラス)を入れておく箱のイメージです。
Laravel サービスプロバイダ
Laravelアプリケーション全体の起動処理における初期起動処理を行っています。
サービスプロバイダからサービスコンテナへDIの設定(コンテナ結合)を行います。
サービスプロバイダーでは、コンテナ結合以外にもイベントリスナ、フィルター、ルーティングの設定なども行います。
(今回は触れません)
DI(Dependency Injection)とは
Dependency Injectionは依存性の注入となります。
抽象クラス(interface)を具象クラスに差し替えて実行できる。
要するにクラスのインスタンス生成処理をサービスコンテナに任せて、クラスの疎結合に保つ仕組み。
疎結合になっていることでテストの時はDBや外部APIを実際に叩かせないように、プログラム実行時にクラスを差し替えできる。
なかなか簡潔に説明するのは難しく、詳細はDI関連のオススメ記事を抜粋したので読んだり、ご自身で調べてみてください。
DIの種類
- コンストラクタインジェクション
- メソッドインジェクション(セッターインジェクション)
- フィールドインジェクション(プロパティインジェクション)
- PHPでは標準実装されていない
DIの種類は3つありますが、コンストラクタインジェクションだけで十分なので覚えておきましょう。
Laravelのフレームワーク内で実行されるコントローラのルーティングに対応しているメソッドやコンソールコマンドのhandle()
メソッドであればメソッドインジェクションを利用できます。(Request
クラスなどよく使われます)
結合: サービスコンテナにクラスを登録する
結合とはサービスコンテナにインターフェースに対応するクラスを登録することです。
登録自体は次章のサービスプロバイダを使って登録します。
- bind
- singleton
- instance
大きく3種類ありますが、特に理由がない限りはbindで結合します。
他にもコンテキストによる結合、プリミティブの結合、型指定した可変引数の結合、タグ付け、結合の拡張等ありますが、必要に迫られたら検討してみてください。
bind(バインド、シンプルな結合)
インターフェース名に対応するクラスを登録する。
サービスコンテナから取り出すときに毎回新しいインスタンスを生成する。
singleton(シングルトンの結合)
インターフェース名に対応するクラスを登録する。
サービスコンテナから初めて取り出すときに新しいインスタンスを生成する。
2回目以降に取り出す時は初回に生成された同じインスタンスが返る。(要は同じインスタンスを使い回しする)
ライフサイクルの記事では、bootstrap/app.php
でKernel
クラスがシングルトン結合されてましたね。
instance(インスタンスの結合)
インターフェース名に対応するインスタンスを登録する。
予め生成したインスタンスをサービスコンテナに登録します。
取り出す時は登録時のインスタンスが返ります。
依存解決: サービスコンテナに登録されたクラスのインスタンスを取り出す
依存解決は結合とは反対にサービスコンテナに登録したクラスのインスタンスを取り出すことです。make
メソッドを利用して取り出すパターンと自動注入(DI)
を利用して取り出すパターンがあります。
特に理由がない限りは 自動注入(DI)
を使って取り出します。
自動注入(DI)
基本はコンストラクタインジェクションを利用します。
Laravelではメソッドインジェクションやルートモデル結合といった便利機能がありますが、やはりコンストラクタインジェクションだけで良いかなと思います。
さいごに
以上でサービスコンテナ編は終了です。
サービスコンテナは難しいと抵抗あるかもしれませんが、クラスを登録して取り出すという実はシンプルな機能です。
次回はサービスプロバイダーの記事です。お楽しみに!