# 機能設計書 41-DIコンテナ

## 概要

本ドキュメントは、Laravel FrameworkのDI（依存性注入）コンテナ機能の設計仕様を定義する。Containerクラスを中心とした依存性解決、バインディング管理、自動解決メカニズムについて詳述する。

### 本機能の処理概要

DIコンテナは、アプリケーション全体で使用されるオブジェクトの生成と依存関係の解決を担う中核的な機能である。クラス間の依存関係を疎結合に保ちながら、必要なオブジェクトを自動的にインスタンス化し、注入する仕組みを提供する。

**業務上の目的・背景**：大規模アプリケーションでは、クラス間の依存関係が複雑化しやすい。DIコンテナを使用することで、依存関係の管理を一元化し、テスタビリティの向上、コードの再利用性の向上、保守性の向上を実現する。これにより、開発者は具体的な実装ではなくインターフェースに対してプログラミングでき、実装の差し替えが容易になる。

**機能の利用シーン**：コントローラー、サービスクラス、リポジトリなど、アプリケーションのあらゆる層で利用される。特に、コントローラのコンストラクタやメソッドへの依存性注入、サービスプロバイダでのバインディング登録、テスト時のモック差し替えなどで活用される。

**主要な処理内容**：
1. バインディングの登録（bind、singleton、scoped、instance）
2. 依存性の解決（make、resolve、build）
3. コンテキスト依存バインディング（when、whenHasAttribute）
4. リゾルビングコールバックの実行
5. 型エイリアスの管理
6. タグ付けとタグによる一括解決

**関連システム・外部連携**：サービスプロバイダ、ファサード、ミドルウェア、ルーティングなどLaravelの各コンポーネントと密接に連携する。

**権限による制御**：コンテナ自体には権限制御は存在しないが、コンテナにバインドされた各サービスにおいて個別に権限制御が実装される。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | - | - | 画面機能マッピングにDIコンテナ関連の画面なし |

## 機能種別

CRUD操作 / オブジェクト生成・管理

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| abstract | string\|Closure | Yes | 解決対象の抽象型（クラス名、インターフェース名、文字列キー） | 空文字不可 |
| concrete | Closure\|string\|null | No | 具象型または生成クロージャ | - |
| shared | bool | No | シングルトンとして登録するかどうか | - |
| parameters | array | No | 解決時に渡すパラメータオーバーライド | - |

### 入力データソース

- サービスプロバイダのregisterメソッド内でのバインディング定義
- アプリケーション内での直接的なmakeメソッド呼び出し
- 設定ファイル（config/*.php）からの設定値

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| instance | object | 解決されたオブジェクトインスタンス |

### 出力先

- アプリケーションコード内の変数
- コントローラのコンストラクタ引数
- メソッドインジェクション対象引数

## 処理フロー

### 処理シーケンス

```
1. バインディング登録
   └─ bind/singleton/scopedメソッドでabstractとconcreteの対応を登録

2. 依存性解決リクエスト
   └─ makeメソッドがresolveメソッドを呼び出し

3. エイリアス解決
   └─ getAliasでエイリアスを実際の抽象型に変換

4. キャッシュ確認
   └─ シングルトンの場合、instancesから既存インスタンスを返却

5. コンテキストバインディング確認
   └─ 現在のビルドスタックに基づくコンテキスト依存バインディングを探索

6. 具象型取得
   └─ getConcreteで登録されている具象型またはクロージャを取得

7. ビルド処理
   └─ buildメソッドでリフレクションを使用してインスタンス生成

8. 依存性の再帰的解決
   └─ resolveDependenciesでコンストラクタ引数を再帰的に解決

9. エクステンダー適用
   └─ extendで登録されたクロージャを順次適用

10. コールバック実行
    └─ resolving/afterResolvingコールバックを実行

11. インスタンス返却
    └─ シングルトンの場合はキャッシュ後に返却
```

### フローチャート

```mermaid
flowchart TD
    A[make/resolve呼び出し] --> B{エイリアス確認}
    B --> C[getAlias でエイリアス解決]
    C --> D{シングルトンとして<br/>キャッシュ済み?}
    D -->|Yes| E[キャッシュから返却]
    D -->|No| F{コンテキスト<br/>バインディング?}
    F -->|Yes| G[コンテキスト具象型取得]
    F -->|No| H[getConcrete で具象型取得]
    G --> I{ビルド可能?}
    H --> I
    I -->|Closure| J[クロージャ実行]
    I -->|Class| K[build でインスタンス生成]
    J --> L[extenders 適用]
    K --> L
    L --> M{shared?}
    M -->|Yes| N[instances にキャッシュ]
    M -->|No| O[コールバック実行]
    N --> O
    O --> P[インスタンス返却]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-41-1 | 循環参照検出 | 依存性解決中に同じ型が再度解決要求された場合、循環依存エラーをスロー | buildStack に同一クラスが存在する場合 |
| BR-41-2 | シングルトン優先 | シングルトンとして登録されている場合、常に同一インスタンスを返却 | shared=true のバインディング |
| BR-41-3 | スコープドインスタンス | scopedとして登録されたバインディングはリクエストごとにクリア可能 | scopedInstances に登録されている型 |
| BR-41-4 | デフォルト値優先 | コンストラクタ引数にデフォルト値があり、バインディングがない場合はデフォルト値を使用 | parameter->isDefaultValueAvailable() |

### 計算ロジック

該当なし

## データベース操作仕様

### 操作別データベース影響一覧

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| - | - | - | DIコンテナ自体はデータベース操作を行わない |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| BindingResolutionException | 解決失敗 | 対象クラスが存在しない、またはインスタンス化不可能 | クラスパスの確認、バインディングの登録 |
| CircularDependencyException | 循環依存 | 依存関係が循環している | 依存関係の見直し、インターフェース抽出 |
| EntryNotFoundException | エントリ未発見 | PSR-11 get()で未バインドの型を解決しようとした | has()で事前確認、バインディング追加 |
| TypeError | 型エラー | bindメソッドの引数が不正 | 正しい型の引数を渡す |

### リトライ仕様

リトライ処理は実装されていない。エラー発生時は即座に例外がスローされる。

## トランザクション仕様

DIコンテナはトランザクション管理を行わない。

## パフォーマンス要件

- 同一リクエスト内でシングルトンは一度のみインスタンス化
- エイリアス解決は再帰的に行われるが、通常1-2段階で完了
- リフレクションのコストを最小化するため、解決結果はresolvedフラグで管理

## セキュリティ考慮事項

- コンテナにバインドされるクラスは信頼されたコードのみ
- 動的なバインディング名の使用時はサニタイゼーションを検討
- シリアライズ時にコンテナ状態が漏洩しないよう注意

## 備考

- PSR-11（ContainerInterface）準拠
- ArrayAccessインターフェース実装により配列アクセス構文でのバインディング取得が可能

---

## コードリーディングガイド

本機能を理解するために参照すべきファイルと、推奨する読み解き順序を以下に示す。

### 推奨読解順序

#### Step 1: データ構造を理解する

コンテナが管理する内部状態を理解することが最初のステップである。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | ContainerContract.php | `src/Illuminate/Contracts/Container/Container.php` | インターフェース定義、コンテナが持つべき公開メソッドを理解 |
| 1-2 | Container.php | `src/Illuminate/Container/Container.php` | プロパティ定義（29-202行目）で管理される状態を把握 |

**読解のコツ**: Container.phpの冒頭に定義されているプロパティ群（$bindings、$instances、$aliases等）を先に把握すると、各メソッドの動作が理解しやすくなる。

#### Step 2: エントリーポイントを理解する

依存性解決の入口となるメソッドを把握する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | Container.php | `src/Illuminate/Container/Container.php` | make() メソッド（862-865行目）が解決処理の入口 |

**主要処理フロー**:
1. **862-865行目**: make()はresolve()を呼び出すラッパー
2. **901-964行目**: resolve()がエイリアス解決からインスタンス返却までの中核処理

#### Step 3: バインディング登録処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | Container.php | `src/Illuminate/Container/Container.php` | bind()（358-394行目）の処理フロー |
| 3-2 | Container.php | `src/Illuminate/Container/Container.php` | singleton()（501-504行目）はshared=trueでbind()を呼び出し |
| 3-3 | Container.php | `src/Illuminate/Container/Container.php` | scoped()（527-532行目）はscopedInstancesにも登録 |

**主要処理フロー**:
- **366行目**: dropStaleInstances()で古いインスタンスを削除
- **378-384行目**: 具象型がClosureでない場合はgetClosure()でラップ
- **386行目**: $bindings配列にconcrete/sharedを登録

#### Step 4: ビルド処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | Container.php | `src/Illuminate/Container/Container.php` | build()（1106-1172行目）がリフレクションでインスタンス生成 |
| 4-2 | Container.php | `src/Illuminate/Container/Container.php` | resolveDependencies()（1212-1249行目）がコンストラクタ引数を解決 |

**主要処理フロー**:
- **1111-1119行目**: Closureの場合は直接実行
- **1122-1125行目**: ReflectionClassでクラス情報取得
- **1130-1132行目**: インスタンス化不可能な場合はnotInstantiable()でエラー
- **1156-1163行目**: コンストラクタの引数を再帰的に解決

#### Step 5: コンテキストバインディングを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | Container.php | `src/Illuminate/Container/Container.php` | when()（210-219行目）でコンテキストバインディング開始 |
| 5-2 | ContextualBindingBuilder.php | `src/Illuminate/Container/ContextualBindingBuilder.php` | needs()/give()でバインディング完了 |
| 5-3 | Container.php | `src/Illuminate/Container/Container.php` | getContextualConcrete()（1052-1070行目）で解決時に参照 |

### プログラム呼び出し階層図

```
Container::make($abstract, $parameters)
    │
    └─ Container::resolve($abstract, $parameters, $raiseEvents)
           │
           ├─ Container::getAlias($abstract)
           │
           ├─ Container::fireBeforeResolvingCallbacks($abstract)
           │
           ├─ Container::getContextualConcrete($abstract)
           │
           ├─ Container::getConcrete($abstract)
           │
           └─ Container::build($concrete)
                  │
                  ├─ ReflectionClass::__construct($concrete)
                  │
                  ├─ Container::resolveDependencies($dependencies)
                  │      │
                  │      ├─ Container::hasParameterOverride($dependency)
                  │      │
                  │      ├─ Container::resolvePrimitive($parameter)
                  │      │
                  │      └─ Container::resolveClass($parameter)
                  │             │
                  │             └─ Container::make($className) [再帰]
                  │
                  └─ new $concrete(...$instances)
```

### データフロー図

```
[入力]                   [処理]                          [出力]

$abstract        ───▶  getAlias()            ───▶  実際の抽象型名
(クラス名/エイリアス)      (エイリアス解決)

$abstract        ───▶  getConcrete()         ───▶  Closure or クラス名
(実際の抽象型)          (具象型取得)

Closure/クラス名  ───▶  build()               ───▶  オブジェクトインスタンス
                     (リフレクション生成)

$parameters      ───▶  resolveDependencies() ───▶  解決済み引数配列
(パラメータ配列)        (依存性解決)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| Container.php | `src/Illuminate/Container/Container.php` | ソース | DIコンテナのメイン実装 |
| BoundMethod.php | `src/Illuminate/Container/BoundMethod.php` | ソース | メソッドインジェクションのサポート |
| ContextualBindingBuilder.php | `src/Illuminate/Container/ContextualBindingBuilder.php` | ソース | コンテキストバインディングのビルダー |
| Util.php | `src/Illuminate/Container/Util.php` | ソース | ユーティリティ関数 |
| RewindableGenerator.php | `src/Illuminate/Container/RewindableGenerator.php` | ソース | タグ解決時のジェネレータ |
| EntryNotFoundException.php | `src/Illuminate/Container/EntryNotFoundException.php` | ソース | PSR-11例外 |
| Container.php | `src/Illuminate/Contracts/Container/Container.php` | コントラクト | インターフェース定義 |
| BindingResolutionException.php | `src/Illuminate/Contracts/Container/BindingResolutionException.php` | コントラクト | 解決失敗例外 |
| CircularDependencyException.php | `src/Illuminate/Contracts/Container/CircularDependencyException.php` | コントラクト | 循環依存例外 |
