# 帳票設計書 11-PHP DIコンテナダンプ

## 概要

本ドキュメントは、Symfony DependencyInjectionコンポーネントにおけるPHP DIコンテナダンプ機能（`PhpDumper`）の設計仕様を定義する。DIコンテナ定義をコンパイル済みPHPクラスとして出力し、本番環境でのパフォーマンス最適化に使用する。

### 本帳票の処理概要

PhpDumperは、Symfonyの依存性注入（DI）コンテナに登録されたサービス定義、パラメータ、エイリアス、プロキシクラスなどの情報を、コンパイル済みPHPクラスファイルとして出力する。

**業務上の目的・背景**：Symfonyアプリケーションでは、リクエストごとにサービスコンテナを構築するのは非効率である。PhpDumperを使用して事前にコンパイル済みのPHPクラスを生成することで、コンテナの初期化コストを大幅に削減し、本番環境のレスポンス性能を向上させる。XMLやYAML形式の設定ファイルの解析やサービス定義の解決が不要となるため、起動時間が劇的に短縮される。

**帳票の利用シーン**：キャッシュウォームアップ時（`cache:warmup`コマンド実行時）やアプリケーションの初回リクエスト時に自動的に生成される。開発環境ではデバッグ情報付きで出力し、本番環境では最適化済みのクラスを生成する。

**主要な出力内容**：
1. サービスファクトリメソッド群を含むコンパイル済みPHPコンテナクラス
2. サービス定義のインライン展開されたファクトリコード
3. パラメータバッグのデフォルト値定義
4. プロキシクラス（遅延初期化用）
5. OPcacheプリロード用ファイル（`as_files`オプション使用時）

**帳票の出力タイミング**：`cache:warmup`コマンド実行時、またはキャッシュが存在しない状態でのアプリケーション起動時に自動生成される。

**帳票の利用者**：Symfonyフレームワーク内部のカーネル起動処理。間接的にはアプリケーション開発者やインフラエンジニアが本番環境デプロイ時に利用する。

## 帳票種別

コンパイル済みPHPクラスファイル（コード生成）

## 利用画面

| 画面No | 画面名 | URL/ルーティング | 出力操作 |
|--------|--------|-----------------|---------|
| N/A | CLIコマンド | `bin/console cache:warmup` | コマンド実行 |
| N/A | カーネル起動 | 自動実行 | 初回リクエスト時の自動生成 |

## 出力形式

### 基本仕様

| 項目 | 内容 |
|-----|------|
| ファイル形式 | PHP |
| 用紙サイズ | N/A（プログラムファイル） |
| 向き | N/A |
| ファイル名 | `{class}.php`（デフォルト: `ProjectServiceContainer.php`） |
| 出力方法 | ファイルシステムへの書き込み（キャッシュディレクトリ） |
| 文字コード | UTF-8 |

### PHP固有設定

| 項目 | 内容 |
|-----|------|
| 名前空間 | `Container{hash}`（as_filesオプション時） |
| 基底クラス | `Symfony\Component\DependencyInjection\Container`（デフォルト） |
| as_filesモード | 有効時は複数ファイルに分割出力 |
| OPcacheプリロード | 対応（preload_classesオプション） |

## 帳票レイアウト

### レイアウト概要

PhpDumperは単一のPHPクラスファイル、またはas_filesオプション有効時には複数ファイルを生成する。

```
┌─────────────────────────────────────┐
│     クラス宣言・use文               │
├─────────────────────────────────────┤
│     コンストラクタ                   │
│     （サービスID→メソッドマッピング）  │
├─────────────────────────────────────┤
│     サービスファクトリメソッド群       │
│     （get{ServiceName}Service()）    │
├─────────────────────────────────────┤
│     非推奨エイリアス定義             │
├─────────────────────────────────────┤
│     getDefaultParameters()          │
│     （パラメータデフォルト値）        │
└─────────────────────────────────────┘
```

### ヘッダー部

| No | 項目名 | 説明 | データ取得元 | 表示形式 |
|----|-------|------|-------------|---------|
| 1 | 名前空間宣言 | コンテナクラスの名前空間 | options['namespace'] | PHP namespace文 |
| 2 | use文 | 依存するクラスのインポート | 自動解析 | PHP use文 |
| 3 | クラス宣言 | コンテナクラスの定義 | options['class'], options['base_class'] | PHP class文 |

### 明細部

| No | 項目名 | 説明 | データ取得元 | 表示形式 | 列幅 |
|----|-------|------|-------------|---------|-----|
| 1 | コンストラクタ | サービスID・メソッドマッピング | ContainerBuilder.getDefinitions() | PHPメソッド | N/A |
| 2 | サービスファクトリ | 各サービスの生成ロジック | Definition.getClass(), getArguments()等 | PHPメソッド | N/A |
| 3 | パラメータ定義 | コンテナパラメータ | ParameterBag.all() | PHP配列 | N/A |
| 4 | プロキシクラス | 遅延初期化用プロキシ | LazyServiceDumper | PHPクラス | N/A |

### フッター部

| No | 項目名 | 説明 | データ取得元 | 表示形式 |
|----|-------|------|-------------|---------|
| 1 | removed-ids | 削除済みサービスID一覧 | ContainerBuilder.getRemovedIds() | PHP配列ファイル |
| 2 | preloadファイル | OPcacheプリロード設定 | preload_classes オプション | PHPスクリプト |

## 出力条件

### 抽出条件

| 条件名 | 説明 | 必須 |
|-------|------|-----|
| コンテナがコンパイル済みであること | `ContainerBuilder.isCompiled()` がtrueであること | Yes |
| クラス名の指定 | options['class'] パラメータ | No（デフォルト: ProjectServiceContainer） |
| 基底クラスの指定 | options['base_class'] パラメータ | No（デフォルト: Container） |

### ソート順

| 優先度 | 項目 | 昇順/降順 |
|-------|------|---------|
| 1 | サービスID | サービス定義の登録順 |

### 改ページ条件

as_filesオプション有効時、各サービスファクトリメソッドが個別ファイルに分割される。

## データベース参照仕様

### 参照テーブル一覧

本帳票はデータベースを直接参照しない。ContainerBuilderオブジェクトから内部データ構造を参照する。

| テーブル名 | 用途 | 結合条件 |
|-----------|------|---------|
| N/A | N/A | N/A |

### テーブル別参照項目詳細

N/A（内部データ構造からの出力）

## 計算仕様

### 計算項目一覧

| 項目名 | 計算式 | 端数処理 | 備考 |
|-------|-------|---------|------|
| コンテナハッシュ | `ContainerBuilder::hash($files)` | N/A | ファイル内容からのハッシュ値 |
| ビルドID | `hash('crc32', $hash.$time)` | N/A | ハッシュとビルド時間からのCRC32 |
| ターゲットディレクトリ正規表現 | ファイルパスの正規表現化 | N/A | パス置換用 |

## 処理フロー

### 出力フロー

```mermaid
flowchart TD
    A[dump()メソッド呼び出し] --> B[オプション初期化]
    B --> C[循環参照解析]
    C --> D[参照解析 analyzeReferences]
    D --> E[デフォルトパラメータメソッド生成]
    E --> F[クラス開始コード生成]
    F --> G[サービスファクトリメソッド生成]
    G --> H[非推奨エイリアス追加]
    H --> I[プロキシクラス生成]
    I --> J{as_filesモード?}
    J -->|Yes| K[複数ファイルに分割]
    K --> L[プリロードファイル生成]
    L --> M[エントリポイントファイル生成]
    J -->|No| N[単一ファイルとして結合]
    M --> O[出力完了]
    N --> O
```

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 表示メッセージ | 対処方法 |
|----------|---------|--------------|---------|
| LogicException | コンテナ未コンパイル | "Cannot dump an uncompiled container." | コンテナをコンパイルしてからダンプする |
| EnvParameterException | 未解決の環境変数 | 環境変数名を含むエラーメッセージ | 環境変数を設定する |
| RuntimeException | ダンプ不可能な値 | "Unable to dump a service container if a parameter is an object or a resource" | パラメータからオブジェクトやリソースを除去する |
| InvalidArgumentException | 不正な引数 | 各種バリデーションメッセージ | 引数を修正する |

## パフォーマンス要件

| 項目 | 内容 |
|-----|------|
| 想定データ件数 | 数百〜数千サービス定義 |
| 目標出力時間 | 数秒以内（大規模アプリケーションでも） |
| 同時出力数上限 | 1（キャッシュウォームアップは排他制御下で実行） |

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

- 生成されるPHPファイルにはサービス定義やパラメータ値が含まれるため、キャッシュディレクトリのファイルパーミッションを適切に設定する必要がある
- 環境変数のプレースホルダはランタイムで解決されるため、ダンプファイルに実際の機密値は含まれない
- `debug`オプション無効時はDocBlockのコメントが省略される

## 備考

- PhpDumperはSymfonyフレームワークの中で最も複雑なDumperであり、約2000行超のコードで構成される
- `as_files`オプション有効時はコンテナが複数ファイルに分割され、OPcacheの効率が向上する
- `inline_factories`オプションと組み合わせることで、さらなる最適化が可能

---

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

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

### 推奨読解順序

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

まず、PhpDumperが入力として受け取るContainerBuilderのデータ構造を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | Dumper.php | `src/Symfony/Component/DependencyInjection/Dumper/Dumper.php` | 基底クラス。ContainerBuilderをコンストラクタで受け取る（行23-26） |
| 1-2 | Definition.php | `src/Symfony/Component/DependencyInjection/Definition.php` | サービス定義のデータ構造。class, arguments, methodCalls, factory等のプロパティ |
| 1-3 | ContainerBuilder.php | `src/Symfony/Component/DependencyInjection/ContainerBuilder.php` | getDefinitions(), getAliases(), getParameterBag()等のデータ取得メソッド |

**読解のコツ**: ContainerBuilderがDefinitionオブジェクトのコレクションを保持し、それをPhpDumperがPHPコードに変換する構造を理解する。

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

PhpDumperのdump()メソッドが処理の起点となる。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | PhpDumper.php | `src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php` | dump()メソッド（行131-399）がエントリーポイント |

**主要処理フロー**:
1. **行99-106**: コンストラクタでコンパイル済みチェック
2. **行131-151**: dump()メソッドでオプション初期化
3. **行184-188**: 循環参照解析と参照解析
4. **行222-228**: コード生成の核心部分（startClass, addServices, addDefaultParametersMethod）
5. **行241-386**: as_filesモード時のファイル分割処理

#### Step 3: サービスファクトリ生成を理解する

各サービス定義からPHPファクトリメソッドを生成する処理。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | PhpDumper.php | `src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php` | addServices()、addService()メソッドでサービス単位のコード生成 |

**主要処理フロー**:
- **addServices()**: 全サービス定義をイテレートしてファクトリメソッドを生成
- **addService()**: 個別サービスのget{ServiceName}Service()メソッドを生成
- **generateProxyClasses()**: 遅延初期化用プロキシクラスを生成

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

```
PhpDumper::dump()
    |
    +-- analyzeReferences()
    |       +-- AnalyzeServiceReferencesPass::process()
    |       +-- CheckCircularReferencesPass::process()
    |
    +-- addDefaultParametersMethod()
    |
    +-- startClass()
    |
    +-- addServices()
    |       +-- addService() [各サービスごと]
    |               +-- addServiceInclude()
    |               +-- addServiceInstance()
    |               +-- addServiceMethodCalls()
    |               +-- addServiceConfigurator()
    |               +-- addServiceReturn()
    |
    +-- addDeprecatedAliases()
    |
    +-- generateProxyClasses()
    |       +-- LazyServiceDumper::getProxyCode()
    |
    +-- endClass()
```

### データフロー図

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

ContainerBuilder  ─────> PhpDumper::dump()  ─────> PHP class file(s)
  |-- Definitions                |                    |-- {Class}.php
  |-- Aliases                    |-- startClass()     |-- removed-ids.php
  |-- ParameterBag               |-- addServices()    |-- proxy-classes.php
  |-- RemovedIds                 |-- endClass()       |-- {Class}.preload.php
  +-- EnvCounters                +-- (file splitting)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| PhpDumper.php | `src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php` | ソース | メインのダンプ処理クラス |
| Dumper.php | `src/Symfony/Component/DependencyInjection/Dumper/Dumper.php` | ソース | 基底クラス（ContainerBuilder保持） |
| DumperInterface.php | `src/Symfony/Component/DependencyInjection/Dumper/DumperInterface.php` | ソース | ダンパーインターフェース |
| ContainerBuilder.php | `src/Symfony/Component/DependencyInjection/ContainerBuilder.php` | ソース | コンテナ定義の管理 |
| Definition.php | `src/Symfony/Component/DependencyInjection/Definition.php` | ソース | サービス定義のデータ構造 |
| LazyServiceDumper.php | `src/Symfony/Component/DependencyInjection/LazyProxy/PhpDumper/LazyServiceDumper.php` | ソース | 遅延サービスプロキシのコード生成 |
| Preloader.php | `src/Symfony/Component/DependencyInjection/Dumper/Preloader.php` | ソース | OPcacheプリロード処理 |
