Skip to main content

サービスコンテナとは

Laravelのサービスコンテナは、クラスの依存関係を管理し、依存性注入を行うための仕組みです。依存性注入とは、クラスが必要とする依存をコンストラクターや、場合によってはセッターメソッドを通じてクラスへ「注入」することを指します。 次の例を見てみましょう。
この例では、PodcastController はApple MusicなどのデータソースからPodcastを取得する必要があります。そこで、Podcastを取得できるサービスを注入します。サービスを注入することで、テスト時にAppleMusicサービスのモック(ダミー実装)を簡単に差し替えられます。
サービスコンテナを深く理解することは、大規模なLaravelアプリケーションを構築するうえで不可欠です。Laravelコア自体への貢献にも役立ちます。

ゼロコンフィギュレーション解決

クラスが他の具体クラス(インターフェースではない)にしか依存していない場合、コンテナにその解決方法を教える必要はありません。例えば、次のコードをroutes/web.phpに書いたとします。
この例はルートファイル内でクラスを定義していますが、これはデモ用です。実際のアプリケーションでは、サービスクラスは app/Services ディレクトリに定義してください。
このルートにアクセスすると、Laravelは自動的にServiceクラスを解決してルートハンドラーへ注入します。設定ファイルを用意しなくても依存性注入の恩恵を受けられます。 コントローラー、イベントリスナー、ミドルウェアなど、Laravelアプリケーションで書くクラスの多くは、コンテナを通じて自動的に依存が注入されます。

バインディング

基本的なバインディング

ほとんどのバインディングはサービスプロバイダ内で登録します。サービスプロバイダ内では $this->app プロパティを通じてコンテナにアクセスできます。

bind

bind メソッドを使って、クラスまたはインターフェース名とクロージャを渡してバインディングを登録します。
クロージャの引数としてコンテナ自身を受け取ることができます。これを使ってサブ依存を解決できます。 サービスプロバイダの外でコンテナを操作したい場合は App ファサードを使います。
インターフェースに依存しないクラスはコンテナへバインドする必要はありません。コンテナはリフレクションを使ってこれらのオブジェクトを自動的に解決できます。

singleton

singleton メソッドは、クラスまたはインターフェースを一度だけ解決するようにバインドします。一度解決されたシングルトンは、以降のコンテナへの呼び出しで同じインスタンスが返されます。
singletonIf メソッドを使うと、指定した型に対するバインディングがまだ登録されていない場合のみシングルトンバインディングを登録できます。

Singleton属性

クラスやインターフェースに #[Singleton] 属性を付けることでも、一度だけ解決されるようコンテナに指示できます。

スコープ付きシングルトンのバインド

scoped メソッドは、クラスまたはインターフェースをLaravelのリクエスト/ジョブのライフサイクル内で一度だけ解決するようにバインドします。singleton メソッドと似ていますが、scoped メソッドで登録されたインスタンスは、Laravel Octane ワーカーが新しいリクエストを処理するときや、キューワーカーが新しいジョブを処理するときなど、Laravelアプリケーションが新しい「ライフサイクル」を開始するたびに破棄されます。
scopedIf メソッドを使うと、指定した型に対するバインディングがまだ登録されていない場合のみスコープ付きバインディングを登録できます。

Scoped属性

クラスやインターフェースに #[Scoped] 属性を付けることでも、リクエスト/ジョブのライフサイクル内で一度だけ解決されるようコンテナに指示できます。

instance

既存のオブジェクトインスタンスを instance メソッドでコンテナにバインドすることもできます。以降のコンテナへの呼び出しでは常にそのインスタンスが返されます。

インターフェースを実装にバインドする

サービスコンテナの強力な機能の一つは、インターフェースを特定の実装にバインドできることです。例えば、EventPusher インターフェースと RedisEventPusher 実装があるとします。
これにより、コンテナは EventPusher の実装が必要なクラスに RedisEventPusher を注入するようになります。あとはコンストラクターで EventPusher インターフェースをタイプヒントするだけです。
インターフェースに依存することで、実装を差し替えてもコードを変更する必要がなくなります。これにより、テストや将来の変更が容易になります。

Bind属性

Laravelはさらに便利な Bind 属性も提供しています。インターフェースにこの属性を付けることで、そのインターフェースが要求されたときにどの実装を自動的に注入するかをLaravelに伝えられます。Bind 属性を使う場合、サービスプロバイダで追加の登録処理を行う必要はありません。 さらに、インターフェースに複数の Bind 属性を配置することで、環境ごとに異なる実装を注入するよう設定することもできます。
また、Singleton属性やScoped属性を併用することで、そのコンテナバインディングを一度だけ解決するか、リクエスト/ジョブごとに一度だけ解決するかを指定できます。

自動解決(型ヒントによるDI)

サービスコンテナは、コントローラー、イベントリスナー、ミドルウェアなどのクラスを解決する際に、コンストラクターの型ヒントを見て依存を自動的に注入します。
UserRepository がインターフェースに依存していなければ、コンテナへの登録は不要です。次のルートにアクセスするだけで、コンテナが自動的に依存を解決してコントローラーに注入します。

コンテナからの解決

makeメソッド

make メソッドを使って、コンテナからクラスインスタンスを解決できます。
クラスの依存がコンテナで解決できない場合、makeWith メソッドを使って追加の引数を渡すこともできます。

自動注入

実際には、make メソッドを直接呼び出すことはほとんどありません。コンテナが解決するクラス(コントローラー、イベントリスナー、ミドルウェアなど)のコンストラクターに型ヒントを追加するだけで、コンテナが自動的に注入してくれます。

ファサードとコンテナの関係

Laravelのファサードは、コンテナ内のオブジェクトへの静的インターフェースを提供します。例えば、Cache::get() は内部的にコンテナから Cache サービスを取得して呼び出しています。
ファサードはコンテナの便利なラッパーです。テスト時にはファサードをモックに差し替えることもできます。

コンストラクターインジェクションの実践例

実際のアプリケーションでの典型的なパターンを見てみましょう。
1

インターフェースを定義する

2

実装クラスを作成する

3

サービスプロバイダでバインドする

4

コントローラーで注入を受け取る

このパターンにより、決済サービスをStripeから別のプロバイダに切り替える場合も、バインディングを1か所変更するだけで対応できます。

次のステップ

サービスプロバイダ

サービスプロバイダを使ってバインディングを登録する方法を学びます。
最終更新日 2026年7月23日