先日DIの記事を書いたんですが、
DIって説明しようとすると、しれっとServiceProviderってやつが出てくるんですよね。
でも、「Providerにbindしてる」って言われても、お前それどこにおんねんってなる。
LaravelのプロジェクトにはProvider
っていうディレクトリがあるんですが、
慣れないうちはそもそも存在に気づかないこともあります。
開発規模によってはそこまで触らないケースもあるかもしれませんが、
仕組みがわかってると、設計の見通しがよくなります。
この記事では、ServiceProviderって何?どこでどう使うの?というあたりを、
“とりあえず動いてるLaravel”からちょっと抜け出したい人向けに整理していきます。
ServiceProviderって、結局なにしてんの?
Laravelが起動する時に、「どのサービスをどう使うか」を先に知っておきたくて、
「あのクラスが必要になったらこれ渡しといてね」って登録しておく場所がServiceProviderです。
たとえばDIでこんなコード書いたとします:
public function __construct(UserRepository $repo)
{
$this->repo = $repo;
}
このとき、LaravelはUserRepository
って型ヒント見て、
「このインターフェース、どうやってインスタンス化するの?」ってなる。
ここでServiceProviderに登録されていれば、Laravelは
$this->app->bind(
UserRepository::class,
EloquentUserRepository::class
);
って設定を読んで、「あー、これね」ってなってくれる。
register()とboot()の違い
AppServiceProvider.php
の中には、だいたいこの2つのメソッドがあります。
public function register()
{
// サービスの登録
}
public function boot()
{
// 登録済みサービスを使った初期化
}
register()
:DIの設定を書く。まだ他のサービスは使えない。boot()
:全サービスが登録されたあとに呼ばれる。イベント登録とか。
ぶっちゃけ最初はregister()
だけ押さえとけばOK。boot()
は「ちょっと複雑な初期化が必要なとき」くらいで。
どこで使う?どう書く?
public function register()
{
$this->app->singleton(MemoPad::class, function () {
return new MemoPad();
});
}
bind()
と singleton()
の違いはざっくりこんな感じ:
メソッド | インスタンス生成タイミング | 使いどころ |
---|---|---|
bind() | 毎回newされる | ステートレスなやつ |
singleton() | 最初の1回だけnewされる | 状態を持たせたいときなど |
何が嬉しいの?
- 依存の解決が明示的になる
→ どこで何が使われてるか見やすい。責務がはっきりする。 - テストが書きやすくなる
→ モックを差し替えるのが簡単になる - 実装を変えても呼び出し側を触らなくて済む
→ EloquentからAPIクライアントに変えたくなったとき、Providerの設定だけ直せばいい
Laravelは「書くだけで渡ってくる快感」があるけど、
その裏側を知っておくと、「設計ってそういうことか」ってなる。
まとめ
ServiceProviderは、Laravelが
「このインターフェース、どう処理すればいい?」って聞きに来る場所。
register()
でサービスを登録するboot()
は初期化に使えるけど最初は無理に使わなくていい- bindとsingletonの違いは使い分けよう(だいたいbindでいい)
- 設計の意図が透けて見えるので、チーム開発でも効く
とりあえず「意味わからんけどAppServiceProviderに書いてる」状態から、
「なるほど、Laravelに“使い方”を教えてるんだな」ってとこまでわかれば十分です。
よかったらDIの記事も読んでみてください!
コメントを残す