# 機能設計書 47-VarExporter

## 概要

本ドキュメントは、Symfony VarExporterコンポーネントの機能設計を記述する。VarExporterはシリアライズ可能なPHPデータ構造をプレーンPHPコードにエクスポートする機能、オブジェクトのハイドレーション機能、コンストラクタなしのインスタンス化機能を提供するコンポーネントである。

### 本機能の処理概要

VarExporterコンポーネントは、PHP標準のvar_export()の改良版として、serialize()のセマンティクスを保持しながらPHPコードへのエクスポートを行う。OPcacheを活用することで、unserialize()よりも高速なデータ復元を実現する。

**業務上の目的・背景**：PHPのvar_export()は多くの型をサポートしておらず、特にオブジェクトの正確なエクスポートに問題がある。VarExporterは、serialize()が扱えるすべてのデータ構造を正確にPHPコードに変換し、OPcacheによる最適化の恩恵を受けることで、キャッシュウォームアップやDIコンテナのコンパイル等の場面で高いパフォーマンスを発揮する。

**機能の利用シーン**：DIコンテナのキャッシュダンプ、ルーティングテーブルのキャッシュ、設定キャッシュのウォームアップ、レイジーロードプロキシの生成、テストフィクスチャの生成等。

**主要な処理内容**：
1. VarExporter::export() - 任意のPHP値をPHPコード文字列にエクスポート
2. Hydrator::hydrate() - オブジェクトのprivate/protectedプロパティを含むハイドレーション
3. Instantiator::instantiate() - コンストラクタを呼ばないオブジェクト生成とプロパティ設定
4. LazyObjectInterface - レイジーロードプロキシの生成とゴーストオブジェクト
5. ProxyHelper - レイジーロードプロキシクラスのコード生成

**関連システム・外部連携**：DependencyInjectionコンポーネント（コンテナダンプ）、Routingコンポーネント（ルートキャッシュ）、Cacheコンポーネント（PhpFilesAdapter）と連携する。

**権限による制御**：VarExporterコンポーネントには権限制御機構はない。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | - | - | VarExporterコンポーネントには関連画面はない |

## 機能種別

データ変換 / シリアライゼーション

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| value (export) | mixed | Yes | エクスポートするPHP値 | リソース型は不可 |
| instance (hydrate) | object | Yes | ハイドレーション対象のオブジェクト | - |
| properties (hydrate) | array | No | 設定するプロパティ | キー: プロパティ名、値: プロパティ値 |
| scopedProperties | array | No | スコープ付きプロパティ | キー: クラス名、値: プロパティ配列 |
| class (instantiate) | string | Yes | インスタンス化するクラス名 | 存在するクラスであること |

### 入力データソース

- アプリケーションコードからの任意のPHPデータ構造
- DIコンテナコンパイラからのサービス定義
- キャッシュウォームアップ処理からの設定データ

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| PHPコード文字列 (export) | string | includeで評価可能なPHPコード |
| isStaticValue | bool | エクスポート値が静的値かどうか |
| foundClasses | array | 値に含まれるクラス名の一覧 |
| object (hydrate/instantiate) | object | ハイドレーション済み/インスタンス化済みオブジェクト |

### 出力先

- ファイルシステム（PHPファイルとしてダンプ）
- OPcache（ダンプされたPHPファイルのキャッシュ）
- メモリ（インスタンス化/ハイドレーション結果）

## 処理フロー

### 処理シーケンス

```
【VarExporter::export()】
1. 入力値の判定
   └─ スカラー値・UnitEnum: Exporter::export()で直接出力
2. オブジェクト/配列の場合
   └─ Exporter::prepare()でオブジェクトグラフの走査
   └─ SplObjectStorageによるオブジェクトプールの構築
   └─ リファレンスの追跡
3. 静的値判定
   └─ isStaticValue=trueなら直接Exporter::export()
4. 非静的値の場合
   └─ クラス情報の抽出
   └─ プロパティの収集（クラス別）
   └─ Hydrator/Registry/Valuesの組み立て
   └─ Exporter::export()で最終出力

【Hydrator::hydrate()】
1. プロパティのスコープ解決
   └─ propertyScopes キャッシュによるプロパティ→クラスマッピング
2. スコープ別のハイドレーション
   └─ simpleHydrators キャッシュによるクロージャ実行
3. ハイドレーション済みオブジェクトの返却

【Instantiator::instantiate()】
1. クラスのリフレクター取得
2. インスタンス生成方式の決定
   └─ cloneable: プロトタイプのクローン
   └─ コンストラクタなし: newInstanceWithoutConstructor()
   └─ Serializable: unserialize()
3. プロパティのハイドレーション
```

### フローチャート

```mermaid
flowchart TD
    A[export value] --> B{スカラー/UnitEnum?}
    B -->|Yes| C[直接エクスポート]
    B -->|No| D[Exporter::prepare]
    D --> E[オブジェクトグラフ走査]
    E --> F{isStaticValue?}
    F -->|Yes| C
    F -->|No| G[クラス/プロパティ抽出]
    G --> H[Hydrator構築]
    H --> I[Exporter::export]
    I --> J[PHPコード文字列]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-47-01 | リソース型不可 | リソース型はエクスポートできない | export()時 |
| BR-47-02 | UnitEnum直接出力 | UnitEnumはそのまま静的値として出力される | export()時 |
| BR-47-03 | インスタンス化不可型 | インスタンス化できない型はNotInstantiableTypeException | instantiate()時 |
| BR-47-04 | privateプロパティアクセス | "\0ClassName\0property"形式でprivateプロパティを指定可能 | hydrate()時 |

### 計算ロジック

特になし。

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

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

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | ExceptionInterface | エクスポートできない値が含まれる場合 | リソース型を含まないデータ構造を使用する |
| - | NotInstantiableTypeException | インスタンス化できないクラスが指定された場合 | インスタンス化可能なクラスを指定する |

### リトライ仕様

該当なし。

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

該当なし。

## パフォーマンス要件

- OPcacheを活用することで、unserialize()よりも高速なデータ復元が可能
- プロパティスコープとハイドレータのキャッシュ（静的変数）によるリフレクション呼び出しの最小化

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

- エクスポートされたPHPコードの実行には注意が必要（信頼できるソースからのコードのみ実行すること）
- unserialize()を内部で使用する場合があるため、デシリアライゼーション攻撃に注意

## 備考

- LazyObjectInterfaceとProxyHelperにより、レイジーロードプロキシパターンをサポート
- Internalディレクトリ内のExporter、Hydrator、Registry、Valuesクラスは内部実装

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | Internal/Registry.php | `src/Symfony/Component/VarExporter/Internal/Registry.php` | クラスリフレクタとプロトタイプのレジストリ |
| 1-2 | Internal/Values.php | `src/Symfony/Component/VarExporter/Internal/Values.php` | リファレンス値の管理 |

#### Step 2: エクスポート処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | VarExporter.php | `src/Symfony/Component/VarExporter/VarExporter.php` | エクスポートのエントリーポイント |

**主要処理フロー**:
1. **40-46行目**: export() - スカラー値/UnitEnumの直接エクスポート判定
2. **48-62行目**: オブジェクトグラフの走査とリファレンスプール構築
3. **64-66行目**: 静的値の直接エクスポート
4. **68-112行目**: クラス情報抽出、プロパティ収集、Hydrator/Registry構築

#### Step 3: ハイドレーションを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | Hydrator.php | `src/Symfony/Component/VarExporter/Hydrator.php` | オブジェクトハイドレーションAPI |

**主要処理フロー**:
- **57-77行目**: hydrate() - プロパティスコープの解決とsimpleHydratorsによるハイドレーション

#### Step 4: インスタンス化を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | Instantiator.php | `src/Symfony/Component/VarExporter/Instantiator.php` | コンストラクタなしインスタンス化 |

**主要処理フロー**:
- **41-58行目**: instantiate() - cloneable/newInstanceWithoutConstructor/unserializeの3方式

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

```
VarExporter::export(value)
    |
    ├─ Exporter::export(value)           [スカラー値]
    |
    └─ Exporter::prepare([value], pool)  [オブジェクト/配列]
           |
           ├─ SplObjectStorage (オブジェクトプール)
           ├─ refsPool (リファレンス追跡)
           |
           └─ Hydrator + Registry + Values
                  └─ Exporter::export(hydrator)

Hydrator::hydrate(instance, properties, scopedProperties)
    |
    ├─ InternalHydrator::getPropertyScopes(class)
    └─ InternalHydrator::getSimpleHydrator(scope)

Instantiator::instantiate(class, properties)
    |
    ├─ Registry::getClassReflector(class)
    ├─ clone / newInstanceWithoutConstructor / unserialize
    └─ Hydrator::hydrate(instance, properties)
```

### データフロー図

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

PHP値                VarExporter::export()           PHPコード文字列
  (object/array)     ├─ オブジェクトグラフ走査         (include可能)
                     ├─ プロパティ抽出
                     └─ PHPコード生成                  OPcache
                                                       (高速復元)

object              Hydrator::hydrate()              ハイドレーション済み
properties          └─ スコープ解決+プロパティ設定    オブジェクト

class               Instantiator::instantiate()      新規インスタンス
properties          └─ コンストラクタ不使用生成       (プロパティ設定済み)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| VarExporter.php | `src/Symfony/Component/VarExporter/VarExporter.php` | ソース | PHPコードエクスポート |
| Hydrator.php | `src/Symfony/Component/VarExporter/Hydrator.php` | ソース | オブジェクトハイドレーション |
| Instantiator.php | `src/Symfony/Component/VarExporter/Instantiator.php` | ソース | コンストラクタなしインスタンス化 |
| ProxyHelper.php | `src/Symfony/Component/VarExporter/ProxyHelper.php` | ソース | レイジーロードプロキシ生成 |
| LazyObjectInterface.php | `src/Symfony/Component/VarExporter/LazyObjectInterface.php` | ソース | レイジーオブジェクトインターフェース |
| Internal/ | `src/Symfony/Component/VarExporter/Internal/` | ソース | 内部実装（Exporter、Hydrator、Registry、Values） |
