# 機能設計書 11-Config

## 概要

本ドキュメントは、Symfony Configコンポーネントの機能設計を記述する。Configコンポーネントは、設定値の検索、読み込み、結合、自動補完、バリデーション機能を提供し、YAML、XML、PHP等の設定ファイル処理を統一的に扱う基盤を構成する。

### 本機能の処理概要

**業務上の目的・背景**：Symfonyアプリケーションでは、Bundle設定、ルーティング定義、サービス定義など多種多様な設定情報を複数の形式（YAML、XML、PHP）で管理する必要がある。Configコンポーネントは、これらの設定情報を統一的に読み込み、正規化、マージ、バリデーションを行うことで、設定の不整合を防ぎ、開発者に一貫した設定管理体験を提供する。

**機能の利用シーン**：アプリケーションのブートストラップ時にBundle設定を読み込む場面、ルーティング設定ファイルをパースする場面、サービスコンテナのコンパイル時に設定ツリーの検証を行う場面で利用される。また、キャッシュの鮮度チェックを通じてパフォーマンスの最適化にも寄与する。

**主要な処理内容**：
1. 設定ファイルの検索・ロード（FileLocator、Loaderチェーン）
2. 設定ツリーの定義とビルド（TreeBuilder、NodeDefinition階層）
3. 設定値の正規化・マージ・ファイナライズ（Processor）
4. キャッシュ管理と鮮度チェック（ConfigCache、ResourceCheckerConfigCache）
5. リソース変更検知（FileResource、DirectoryResource、GlobResource等）

**関連システム・外部連携**：DependencyInjectionコンポーネント（サービスコンテナのコンパイル）、FrameworkBundle（アプリケーション設定の統合）、Routingコンポーネント（ルーティング設定ファイルのロード）と密接に連携する。

**権限による制御**：本コンポーネントは設定読み込みの基盤であり、権限による制御は行わない。ファイルシステムのアクセス権限に依存する。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 35 | 設定パネル | 補助機能 | Configコンポーネントで管理される設定値の表示 |

## 機能種別

設定読み込み・バリデーション処理 / キャッシュ管理

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| resource | string/mixed | Yes | 読み込む設定リソース（ファイルパス、Glob パターン等） | ファイルの存在チェック、循環参照チェック |
| type | string/null | No | リソースの種別（yaml、xml等） | サポートされたローダーが存在すること |
| configs | array | Yes | マージ対象の設定配列群 | 設定ツリーに基づくバリデーション |
| file | string | Yes | キャッシュファイルの絶対パス | 絶対パスであること |
| debug | bool | Yes | デバッグモードフラグ | boolean値 |

### 入力データソース

設定ファイル（YAML、XML、PHP）、環境変数、コンパイル時の設定配列

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| processedConfig | array | 正規化・マージ・バリデーション済みの設定配列 |
| cachedContent | string | キャッシュファイルに書き出されたコンテンツ |
| isFresh | bool | キャッシュの鮮度チェック結果 |
| locatedPath | string/string[] | FileLocatorで解決されたファイルパス |

### 出力先

メモリ上の設定配列（DIコンテナ等に渡される）、ファイルシステム上のキャッシュファイル

## 処理フロー

### 処理シーケンス

```
1. 設定ファイルの検索（FileLocator::locate）
   └─ 事前定義されたパス配列から指定ファイルを検索し、絶対パスを返却
2. 設定ファイルのロード（FileLoader::load / DelegatingLoader::load）
   └─ LoaderResolverでリソース種別に対応するローダーを選択しロード実行
3. インポート処理（FileLoader::import）
   └─ Glob パターン対応、循環参照チェック付きのリソースインポート
4. 設定ツリーの構築（TreeBuilder::buildTree）
   └─ ルートノードから再帰的にNodeDefinition階層をNodeInterface階層に変換
5. 設定の正規化（NodeInterface::normalize）
   └─ YAML/XML形式の差異を吸収する正規化処理
6. 設定のマージ（NodeInterface::merge）
   └─ 複数の設定ソースからの値を統合
7. 設定のファイナライズ（NodeInterface::finalize）
   └─ 必須チェック、型チェック等のバリデーション実行
8. キャッシュ書き込み（ResourceCheckerConfigCache::write）
   └─ 処理結果とメタデータ（リソース情報）をファイルに書き出し
```

### フローチャート

```mermaid
flowchart TD
    A[設定ファイル要求] --> B[FileLocator::locate]
    B --> C{ファイル存在?}
    C -->|Yes| D[Loader::load]
    C -->|No| E[FileLocatorFileNotFoundException]
    D --> F{インポートあり?}
    F -->|Yes| G[FileLoader::import]
    G --> H{循環参照?}
    H -->|Yes| I[CircularReferenceException]
    H -->|No| D
    F -->|No| J[TreeBuilder::buildTree]
    J --> K[Processor::process]
    K --> L[normalize → merge → finalize]
    L --> M{バリデーション成功?}
    M -->|Yes| N[ConfigCache::write]
    M -->|No| O[InvalidConfigurationException]
    N --> P[完了]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-11-01 | キャッシュ鮮度チェック | debugモードがfalseの場合、キャッシュファイルが存在すれば常にfreshとみなす | ConfigCache::isFresh() |
| BR-11-02 | 循環参照禁止 | 設定ファイルのインポートにおいて循環参照を検出した場合は例外をスロー | FileLoader::import() |
| BR-11-03 | 設定正規化 | YAML/XMLの構造差異（単数/複数形キー等）を正規化してから処理する | Processor::normalizeConfig() |
| BR-11-04 | リソースチェッカーの権限性 | 最初にサポートを表明したResourceCheckerの判定結果が最終決定となる | ResourceCheckerConfigCache::isFresh() |

### 計算ロジック

キャッシュ鮮度判定: リソースのタイムスタンプとキャッシュファイルのmtime比較。ResourceCheckerチェーンにおいて、サポートするチェッカーが見つからないリソースは暗黙的にfreshとみなされる。

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

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

本コンポーネントはデータベース操作を行わない。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | FileLocatorFileNotFoundException | 指定ファイルが検索パス内に見つからない | ファイルパスと検索パスの設定を確認 |
| - | FileLoaderImportCircularReferenceException | 設定ファイルのインポートで循環参照を検出 | インポートチェーンの依存関係を見直す |
| - | LoaderLoadException | 対応するローダーが見つからない、またはロード中のエラー | リソース種別と登録済みローダーを確認 |
| - | InvalidConfigurationException | 設定値がツリー定義に違反 | 設定値を定義に従って修正 |
| - | InvalidArgumentException | 空のファイル名等の不正入力 | 入力値を確認 |

### リトライ仕様

リトライは行わない。設定読み込みはアプリケーション起動時に1回実行される。

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

トランザクション管理は行わない。キャッシュファイルの書き込みはFilesystem::dumpFileによるアトミック書き込みで安全性を確保する。

## パフォーマンス要件

- キャッシュ有効時（非デバッグモード）: キャッシュファイルの存在チェックのみで完了するため高速
- キャッシュ無効時（デバッグモード）: 各リソースの鮮度チェックを実行。リソース数に比例した処理時間
- opcache連携: キャッシュファイル書き込み後にopcache_invalidateを実行して即時反映

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

- キャッシュファイルのパーミッションは0666（umask適用後）で作成される
- メタデータファイルのunserialize時にエラーハンドラを設定し、不正なシリアライズデータに対する安全性を確保
- ファイルパスのバリデーション（絶対パス判定）により、ディレクトリトラバーサルを防止

## 備考

- ConfigコンポーネントはSymfonyフレームワークの基盤コンポーネントであり、ほぼすべてのBundleが依存する
- SkippingResourceCheckerにより特定のリソースタイプの鮮度チェックをスキップ可能
- メタデータはPHPシリアライズ形式とJSON形式の両方で保存される

---

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

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

### 推奨読解順序

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

まず、設定ツリーを構成するノードインターフェースとリソースインターフェースを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | ConfigCacheInterface.php | `src/Symfony/Component/Config/ConfigCacheInterface.php` | キャッシュの基本インターフェース（getPath、isFresh、write） |
| 1-2 | ResourceInterface.php | `src/Symfony/Component/Config/Resource/ResourceInterface.php` | リソース変更検知の基本インターフェース |
| 1-3 | NodeInterface.php | `src/Symfony/Component/Config/Definition/NodeInterface.php` | 設定ツリーノードの基本インターフェース（normalize、merge、finalize） |
| 1-4 | LoaderInterface.php | `src/Symfony/Component/Config/Loader/LoaderInterface.php` | ローダーの基本インターフェース（load、supports） |

**読解のコツ**: Configコンポーネントは「設定の読み込み」「設定の検証」「設定のキャッシュ」の3つの責務に分かれている。各サブディレクトリ（Loader、Definition、Resource）がそれぞれの責務に対応する。

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

設定処理のエントリーポイントであるProcessorとConfigCacheを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | Processor.php | `src/Symfony/Component/Config/Definition/Processor.php` | 設定処理の中核。processConfigurationメソッドがメインエントリーポイント |
| 2-2 | ConfigCache.php | `src/Symfony/Component/Config/ConfigCache.php` | キャッシュ管理のエントリーポイント。debugモードに応じた鮮度チェック |

**主要処理フロー**:
1. **28-51行目（ConfigCache）**: ResourceCheckerConfigCacheを継承し、debugモードに応じたチェッカーを設定
2. **59-66行目（ConfigCache）**: isFresh()でdebug=falseかつファイル存在時は即座にtrueを返却
3. **28-37行目（Processor）**: normalize → merge → finalizeの3ステップで設定配列を処理
4. **44-47行目（Processor）**: processConfigurationでConfigurationInterfaceからツリーを構築し処理

#### Step 3: 設定ファイルの読み込み層

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | FileLocator.php | `src/Symfony/Component/Config/FileLocator.php` | ファイルパスの解決ロジック。絶対パス判定とパス配列からの検索 |
| 3-2 | Loader.php | `src/Symfony/Component/Config/Loader/Loader.php` | ローダーの基底クラス。import/resolveによるチェーンパターン |
| 3-3 | FileLoader.php | `src/Symfony/Component/Config/Loader/FileLoader.php` | ファイルベースローダー。Globパターン対応のインポート処理 |
| 3-4 | DelegatingLoader.php | `src/Symfony/Component/Config/Loader/DelegatingLoader.php` | LoaderResolverに委譲するローダー |

**主要処理フロー**:
- **38-77行目（FileLocator）**: locate()メソッド。空文字チェック、絶対パスチェック、パス配列からの探索
- **68-94行目（FileLoader）**: import()メソッド。Globパターン解析、除外パターン対応、doImport呼び出し
- **131-182行目（FileLoader）**: doImport()メソッド。循環参照チェック、ローダー解決と実行

#### Step 4: 設定ツリーの定義と構築

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | TreeBuilder.php | `src/Symfony/Component/Config/Definition/Builder/TreeBuilder.php` | 設定ツリービルダー。getRootNode/buildTreeが主要メソッド |
| 4-2 | BaseNode.php | `src/Symfony/Component/Config/Definition/BaseNode.php` | ノード基底クラス。normalize/merge/finalizeの実装 |
| 4-3 | ArrayNode.php | `src/Symfony/Component/Config/Definition/ArrayNode.php` | 配列ノード。子ノードの管理とマージロジック |

**主要処理フロー**:
- **34-38行目（TreeBuilder）**: コンストラクタでNodeBuilderを使用してルートノードを生成
- **58-61行目（TreeBuilder）**: buildTree()でノード定義階層をノードインスタンス階層に変換

#### Step 5: キャッシュとリソース管理

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | ResourceCheckerConfigCache.php | `src/Symfony/Component/Config/ResourceCheckerConfigCache.php` | キャッシュの実体。isFresh/writeの実装 |
| 5-2 | FileResource.php | `src/Symfony/Component/Config/Resource/FileResource.php` | ファイルリソースの変更検知 |
| 5-3 | GlobResource.php | `src/Symfony/Component/Config/Resource/GlobResource.php` | Globパターンによるリソース群の変更検知 |

**主要処理フロー**:
- **55-98行目（ResourceCheckerConfigCache）**: isFresh()。キャッシュファイル存在チェック、メタデータ読み込み、各リソースの鮮度チェック
- **108-146行目（ResourceCheckerConfigCache）**: write()。コンテンツ書き込み、メタデータのシリアライズ/JSON保存、opcache無効化

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

```
Processor::processConfiguration()
    │
    ├─ ConfigurationInterface::getConfigTreeBuilder()
    │      └─ TreeBuilder::buildTree()
    │             └─ NodeDefinition::getNode()（再帰的にノードツリーを構築）
    │
    └─ Processor::process()
           ├─ NodeInterface::normalize()（各設定配列を正規化）
           ├─ NodeInterface::merge()（正規化済み配列をマージ）
           └─ NodeInterface::finalize()（バリデーション・デフォルト値適用）

FileLoader::import()
    │
    ├─ FileLoader::glob()
    │      └─ FileLocator::locate()
    │
    └─ FileLoader::doImport()
           ├─ Loader::resolve()
           │      └─ LoaderResolver::resolve()
           └─ Loader::load()

ConfigCache::isFresh()
    │
    └─ ResourceCheckerConfigCache::isFresh()
           ├─ safelyUnserialize()（メタデータ読み込み）
           └─ ResourceCheckerInterface::isFresh()（各リソースの鮮度チェック）
```

### データフロー図

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

設定ファイル群       ───▶ FileLocator（パス解決）      ───▶ 絶対パス
(YAML/XML/PHP)             │
                           ▼
                    Loader（ファイル読み込み）           ───▶ 設定配列
                           │
                           ▼
                    Processor（正規化・マージ・検証）   ───▶ 処理済み設定配列
                           │
                           ▼
                    ConfigCache（キャッシュ書き込み）   ───▶ キャッシュファイル + メタデータ
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| ConfigCache.php | `src/Symfony/Component/Config/ConfigCache.php` | ソース | デバッグモード対応キャッシュ管理 |
| ResourceCheckerConfigCache.php | `src/Symfony/Component/Config/ResourceCheckerConfigCache.php` | ソース | リソースチェッカーベースのキャッシュ |
| FileLocator.php | `src/Symfony/Component/Config/FileLocator.php` | ソース | ファイルパス解決 |
| Processor.php | `src/Symfony/Component/Config/Definition/Processor.php` | ソース | 設定の正規化・マージ・ファイナライズ |
| TreeBuilder.php | `src/Symfony/Component/Config/Definition/Builder/TreeBuilder.php` | ソース | 設定ツリーの定義・構築 |
| BaseNode.php | `src/Symfony/Component/Config/Definition/BaseNode.php` | ソース | ノード基底クラス |
| ArrayNode.php | `src/Symfony/Component/Config/Definition/ArrayNode.php` | ソース | 配列ノードの実装 |
| Loader.php | `src/Symfony/Component/Config/Loader/Loader.php` | ソース | ローダー基底クラス |
| FileLoader.php | `src/Symfony/Component/Config/Loader/FileLoader.php` | ソース | ファイルベースローダー |
| DelegatingLoader.php | `src/Symfony/Component/Config/Loader/DelegatingLoader.php` | ソース | 委譲ローダー |
| LoaderResolver.php | `src/Symfony/Component/Config/Loader/LoaderResolver.php` | ソース | ローダー解決 |
| FileResource.php | `src/Symfony/Component/Config/Resource/FileResource.php` | ソース | ファイルリソース |
| DirectoryResource.php | `src/Symfony/Component/Config/Resource/DirectoryResource.php` | ソース | ディレクトリリソース |
| GlobResource.php | `src/Symfony/Component/Config/Resource/GlobResource.php` | ソース | Globパターンリソース |
| SelfCheckingResourceChecker.php | `src/Symfony/Component/Config/Resource/SelfCheckingResourceChecker.php` | ソース | 自己チェック型リソースチェッカー |
