# 機能設計書 29-PropertyInfo

## 概要

本ドキュメントは、Symfony PropertyInfoコンポーネントの機能設計を記述する。このコンポーネントはPHPクラスのプロパティに関するメタデータ（型情報、説明、アクセス可能性等）を抽出するライブラリを提供する。

### 本機能の処理概要

**業務上の目的・背景**：PHPクラスのプロパティに関するメタ情報（型、説明、読み取り/書き込み可否等）は、シリアライゼーション、フォーム生成、バリデーション、API文書生成等の多くの場面で必要となる。しかし、これらの情報はPHPの型宣言、PHPDoc、属性、シリアライザーメタデータ等の様々なソースに分散している。PropertyInfoコンポーネントは複数の情報源からプロパティメタデータを統一的に抽出するインターフェースを提供する。

**機能の利用シーン**：Serializerでの型情報に基づくデシリアライゼーション、Formコンポーネントでのフォームフィールド型推定、Validatorでの自動バリデーションルール推定、PropertyAccessでの読み書き方法の決定、API Platform等のメタデータ生成。

**主要な処理内容**：
1. PropertyInfoExtractorによる複数エクストラクターの統合（最初にnon-nullを返すエクストラクターの結果を使用）
2. PropertyListExtractorInterface：クラスのプロパティ一覧の抽出
3. PropertyTypeExtractorInterface：プロパティの型情報の抽出（TypeInfoのType返却）
4. PropertyDescriptionExtractorInterface：プロパティの短い/長い説明の抽出
5. PropertyAccessExtractorInterface：プロパティの読み取り/書き込み可否の判定
6. PropertyInitializableExtractorInterface：プロパティのコンストラクタ初期化可否の判定
7. ReflectionExtractor：PHPリフレクションに基づくプロパティ情報抽出
8. PhpDocExtractor/PhpStanExtractor：PHPDocコメントからの型情報抽出
9. SerializerExtractor：Serializerメタデータからのプロパティ一覧抽出

**関連システム・外部連携**：TypeInfo（型表現）、PropertyAccess（プロパティアクセス方法の決定）、Serializer（メタデータ統合）、Doctrine（ORMメタデータからの型抽出）と連携する。

**権限による制御**：直接的な権限制御はない。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | （直接的な画面関連なし） | - | バックエンドメタデータ抽出 |

## 機能種別

ユーティリティ / プロパティメタデータ抽出

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| class | string | Yes | 対象クラスのFQCN | 存在するクラス名 |
| property | string | Yes（型/説明/アクセス情報取得時） | プロパティ名 | クラス内に存在するプロパティ |
| context | array | No | コンテキスト情報 | エクストラクターに依存 |

### 入力データソース

PHPクラスのリフレクション情報、PHPDocコメント、属性メタデータ、Serializerマッピング情報

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| properties | array/null | プロパティ名の配列 |
| type | Type/null | TypeInfoのTypeインスタンス |
| shortDescription | string/null | プロパティの短い説明 |
| longDescription | string/null | プロパティの長い説明 |
| isReadable | bool/null | 読み取り可能かどうか |
| isWritable | bool/null | 書き込み可能かどうか |
| isInitializable | bool/null | コンストラクタで初期化可能か |

### 出力先

PHP値

## 処理フロー

### 処理シーケンス

```
1. PropertyInfoExtractorへのクエリ
   └─ 適切なメソッド（getProperties, getType, isReadable等）を呼び出す
2. エクストラクターチェーンの走査
   └─ 登録されたエクストラクターを順に試行
3. 最初の非null結果を返却
   └─ null以外の値を返したエクストラクターの結果を採用
```

### フローチャート

```mermaid
flowchart TD
    A[getType呼び出し] --> B[typeExtractorsループ]
    B --> C{extractor.getType != null?}
    C -->|Yes| D[結果返却]
    C -->|No| E{次のextractorあり?}
    E -->|Yes| B
    E -->|No| F[null返却]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-29-01 | 最初の非null優先 | 複数エクストラクターが登録されている場合、最初に非nullを返したものが使用される | 全メタデータ取得 |
| BR-29-02 | エクストラクター種別分離 | list/type/description/access/initializableのエクストラクターはそれぞれ独立して設定される | PropertyInfoExtractor構築時 |
| BR-29-03 | ReflectionExtractorのマジックメソッド制御 | enable_magic_methods_extractionオプションでマジックメソッド対応を制御 | ReflectionExtractor使用時 |

### 計算ロジック

特になし。

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

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

直接的なデータベース操作は行わない。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | なし | 該当するエクストラクターがない場合はnullを返却 | エラーではなくnullを返す設計 |

### リトライ仕様

リトライは不要。

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

直接的なトランザクション管理は行わない。

## パフォーマンス要件

リフレクション操作は比較的高コストであるため、PropertyInfoCacheDecoratorによるキャッシュ化が推奨される。

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

特別なセキュリティ上の考慮事項はない。

## 備考

PropertyInfoは他の多くのSymfonyコンポーネント（Serializer、PropertyAccess、Validator等）の基盤として機能する重要なメタデータ抽出レイヤーである。TypeInfo Typeを返すgetType()メソッドはSymfony 7.1以降の新しいAPI。

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | PropertyInfoExtractorInterface.php | `src/Symfony/Component/PropertyInfo/PropertyInfoExtractorInterface.php` | 統合インターフェース（getProperties, getType等を含む） |
| 1-2 | PropertyListExtractorInterface.php | `src/Symfony/Component/PropertyInfo/PropertyListExtractorInterface.php` | プロパティ一覧抽出インターフェース |
| 1-3 | PropertyTypeExtractorInterface.php | `src/Symfony/Component/PropertyInfo/PropertyTypeExtractorInterface.php` | 型情報抽出インターフェース（Type返却） |
| 1-4 | PropertyAccessExtractorInterface.php | `src/Symfony/Component/PropertyInfo/PropertyAccessExtractorInterface.php` | アクセス可否判定インターフェース |
| 1-5 | PropertyReadInfo.php | `src/Symfony/Component/PropertyInfo/PropertyReadInfo.php` | 読み取り情報データクラス |
| 1-6 | PropertyWriteInfo.php | `src/Symfony/Component/PropertyInfo/PropertyWriteInfo.php` | 書き込み情報データクラス |

**読解のコツ**: PropertyInfoは複数の抽出インターフェースの集約パターンを採用している。各インターフェースは独立しており、エクストラクターは必要なインターフェースのみを実装できる。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | PropertyInfoExtractor.php | `src/Symfony/Component/PropertyInfo/PropertyInfoExtractor.php` | 統合エクストラクターの実装 |

**主要処理フロー**:
1. **32-38行目**: コンストラクタで5種類のエクストラクターイテラブルを受け取る
2. **41-44行目**: getProperties()でlistExtractorsからextract()
3. **56-65行目**: getType()でtypeExtractorsを順次試行し、最初のnon-null Typeを返却
4. **67-70行目**: isReadable()でaccessExtractorsからextract()
5. **77-80行目**: isInitializable()でinitializableExtractorsからextract()
6. **88-97行目**: extract()ヘルパーでイテラブルを走査し最初のnon-null結果を返却

#### Step 3: ReflectionExtractorを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | ReflectionExtractor.php | `src/Symfony/Component/PropertyInfo/Extractor/ReflectionExtractor.php` | リフレクションベースの最も基本的なエクストラクター |

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

```
PropertyInfoExtractor::getType()
    |
    +-- [foreach] typeExtractors
           |
           +-- ReflectionExtractor::getType()
           |       +-- ReflectionClass / ReflectionProperty / ReflectionMethod
           |       +-- TypeResolver::resolve()
           |
           +-- PhpDocExtractor::getType()
           |       +-- PhpDocParser
           |
           +-- PhpStanExtractor::getType()
                   +-- PHPStan PhpDocParser

PropertyInfoExtractor::getProperties()
    |
    +-- [foreach] listExtractors
           |
           +-- ReflectionExtractor::getProperties()
           |       +-- ReflectionClass::getProperties()
           |       +-- ReflectionClass::getMethods()
           |
           +-- SerializerExtractor::getProperties()
                   +-- ClassMetadataFactory
```

### データフロー図

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

FQCN + property ----------> PropertyInfoExtractor --------> Type / string / bool / null
                                |
                           typeExtractors
                           listExtractors
                           descriptionExtractors
                           accessExtractors
                           initializableExtractors
                                |
                           [最初のnon-null結果]
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| PropertyInfoExtractor.php | `src/Symfony/Component/PropertyInfo/PropertyInfoExtractor.php` | ソース | 統合エクストラクター |
| PropertyInfoExtractorInterface.php | `src/Symfony/Component/PropertyInfo/PropertyInfoExtractorInterface.php` | ソース | 統合インターフェース |
| PropertyListExtractorInterface.php | `src/Symfony/Component/PropertyInfo/PropertyListExtractorInterface.php` | ソース | 一覧抽出インターフェース |
| PropertyTypeExtractorInterface.php | `src/Symfony/Component/PropertyInfo/PropertyTypeExtractorInterface.php` | ソース | 型抽出インターフェース |
| PropertyDescriptionExtractorInterface.php | `src/Symfony/Component/PropertyInfo/PropertyDescriptionExtractorInterface.php` | ソース | 説明抽出インターフェース |
| PropertyAccessExtractorInterface.php | `src/Symfony/Component/PropertyInfo/PropertyAccessExtractorInterface.php` | ソース | アクセス判定インターフェース |
| PropertyInitializableExtractorInterface.php | `src/Symfony/Component/PropertyInfo/PropertyInitializableExtractorInterface.php` | ソース | 初期化可否判定インターフェース |
| PropertyReadInfo.php | `src/Symfony/Component/PropertyInfo/PropertyReadInfo.php` | ソース | 読み取り情報データクラス |
| PropertyWriteInfo.php | `src/Symfony/Component/PropertyInfo/PropertyWriteInfo.php` | ソース | 書き込み情報データクラス |
| PropertyReadInfoExtractorInterface.php | `src/Symfony/Component/PropertyInfo/PropertyReadInfoExtractorInterface.php` | ソース | 読み取り情報抽出インターフェース |
| PropertyWriteInfoExtractorInterface.php | `src/Symfony/Component/PropertyInfo/PropertyWriteInfoExtractorInterface.php` | ソース | 書き込み情報抽出インターフェース |
| ReflectionExtractor.php | `src/Symfony/Component/PropertyInfo/Extractor/ReflectionExtractor.php` | ソース | リフレクションベースエクストラクター |
| PhpDocExtractor.php | `src/Symfony/Component/PropertyInfo/Extractor/PhpDocExtractor.php` | ソース | PHPDocベースエクストラクター |
| PhpStanExtractor.php | `src/Symfony/Component/PropertyInfo/Extractor/PhpStanExtractor.php` | ソース | PHPStanベースエクストラクター |
| SerializerExtractor.php | `src/Symfony/Component/PropertyInfo/Extractor/SerializerExtractor.php` | ソース | Serializerベースエクストラクター |
| PropertyInfoCacheDecorator.php | `src/Symfony/Component/PropertyInfo/PropertyInfoCacheDecorator.php` | ソース | キャッシュデコレーター |
