# 機能設計書 34-Form

## 概要

本ドキュメントは、Symfony Formコンポーネントの機能設計を記述する。Formコンポーネントは、HTMLフォームの作成、処理、再利用を容易にするフレームワークを提供する。

### 本機能の処理概要

Formコンポーネントは、フォーム型（FormType）の定義、フォームのビルド、データの送信処理、データ変換（ModelTransformer/ViewTransformer）、バリデーション統合を一貫したAPIで提供する。3層のデータ表現（モデル、正規化、ビュー）を持つアーキテクチャにより、柔軟なデータ変換を実現する。

**業務上の目的・背景**：Webアプリケーションにおいてフォームの作成と処理は最も頻繁に行われる作業の一つである。Formコンポーネントは、フォームの構造定義、レンダリング、送信データの処理、バリデーションを統合的に管理し、コードの再利用性と保守性を大幅に向上させる。複合フォーム（ネストされたフォーム）、コレクションフォーム、動的フォームフィールドなど、複雑なフォーム要件にも対応する。

**機能の利用シーン**：ユーザー登録フォーム、検索フォーム、管理画面のCRUDフォーム、マルチステップフォーム、ファイルアップロードフォームなど、あらゆるHTMLフォーム処理で使用される。API開発ではフォームの代わりにSerializerを使用することもあるが、Formコンポーネントのバリデーションとデータバインディング機能はAPIでも活用できる。

**主要な処理内容**：
1. FormTypeの定義とビルド（FormFactory / FormBuilder）
2. フォームツリーの構築（親子関係を持つFormインスタンスの階層）
3. データバインディング（submit/handleRequest）
4. データ変換（ModelTransformer / ViewTransformer）
5. バリデーション統合（Validatorコンポーネントとの連携）
6. フォームイベント（PRE_SET_DATA, POST_SET_DATA, PRE_SUBMIT, SUBMIT, POST_SUBMIT）
7. フォームビュー生成（FormView）
8. フォームタイプ推測（FormTypeGuesser）
9. フォームフロー（FormFlow - マルチステップフォーム）

**関連システム・外部連携**：Validatorコンポーネント（バリデーション統合）、Twig Bridge（フォームレンダリング）、CSRF（CSRFトークン保護）、PropertyAccessコンポーネント（データマッピング）、SecurityBundle（CSRF保護統合）と連携する。

**権限による制御**：フォーム自体には権限制御はないが、CSRFトークンによるリクエスト偽造防止機能が組み込まれている。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 23 | フォームパネル | 主機能 | Formコンポーネントで作成されたフォームの構造・データ変換情報の表示 |
| 43 | フォームレイアウト（div） | 主機能 | div要素ベースの標準フォームレイアウトテーマによるフォームレンダリング |
| 44 | フォームレイアウト（table） | 主機能 | table要素ベースのフォームレイアウトテーマによるフォームレンダリング |
| 45-53 | フォームレイアウト（Bootstrap/Foundation/Tailwind） | 主機能 | 各CSSフレームワーク対応のフォームレイアウトテーマ |

## 機能種別

フォーム処理（データバインディング / バリデーション / レンダリング）

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| type | string | Yes | フォームタイプのクラス名（例：TextType::class） | 存在するFormTypeクラスであること |
| data | mixed | No | フォームにバインドする初期データ | - |
| options | array | No | フォームオプション（label, required, constraints等） | FormTypeの定義に従う |
| name | string | No | フォーム名（createNamedBuilder使用時） | 有効な文字列 |

### 入力データソース

- フォームオプション配列（プログラムからの直接入力）
- エンティティ/DTOオブジェクト（データバインディング）
- HTTPリクエスト（submit/handleRequest経由）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| form | FormInterface | 構築されたフォームインスタンス |
| formView | FormView | レンダリング用のフォームビュー |
| data | mixed | フォームから取得したデータ（送信後） |
| errors | FormErrorIterator | フォームエラーのイテレータ |

### 出力先

- フォームビュー（テンプレートエンジンでのHTML出力）
- バインドされたデータ（プログラムでの利用）

## 処理フロー

### 処理シーケンス

```
1. フォームの作成
   ├─ FormFactory::create() / createNamed() / createBuilder()
   ├─ FormRegistry::getType() でResolvedFormType取得
   ├─ ResolvedFormType::createBuilder() でFormBuilder生成
   └─ ResolvedFormType::buildForm() でフォーム構築
2. データの設定
   └─ Form::setData() / PRE_SET_DATA / POST_SET_DATA イベント
3. フォームの送信
   ├─ Form::submit() / handleRequest()
   ├─ PRE_SUBMIT イベント
   ├─ ViewTransformer::reverseTransform()
   ├─ SUBMIT イベント
   ├─ ModelTransformer::reverseTransform()
   └─ POST_SUBMIT イベント（バリデーション実行）
4. フォームビュー生成
   ├─ Form::createView()
   └─ ResolvedFormType::buildView() / finishView()
```

### フローチャート

```mermaid
flowchart TD
    A[FormFactory::create] --> B[FormRegistry::getType]
    B --> C[ResolvedFormType::createBuilder]
    C --> D[FormBuilder構築]
    D --> E[buildForm イベント]
    E --> F[Form::getForm]
    F --> G{データ設定?}
    G -->|Yes| H[setData / PRE_SET_DATA / POST_SET_DATA]
    G -->|No| I[handleRequest / submit]
    H --> I
    I --> J[PRE_SUBMIT]
    J --> K[ViewTransformer::reverseTransform]
    K --> L[SUBMIT]
    L --> M[ModelTransformer::reverseTransform]
    M --> N[POST_SUBMIT / Validation]
    N --> O{バリデーション結果}
    O -->|Valid| P[getData で結果取得]
    O -->|Invalid| Q[getErrors でエラー取得]
    P --> R[createView]
    Q --> R
    R --> S[テンプレートレンダリング]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-34-01 | 3層データ表現 | model, normalized, viewの3つのデータ表現を持ち、Transformerで相互変換する | 常時 |
| BR-34-02 | コンパウンドフォーム | compound=trueのフォームは子フォームを持ち、データを子にマッピングする | compound=true設定時 |
| BR-34-03 | CSRF保護 | CSRFトークンフィールドを自動追加し、送信時にトークンを検証する | csrf_protection=true設定時 |
| BR-34-04 | フォームイベント | ライフサイクルの各段階でイベントをディスパッチし、動的なフォーム修正を可能にする | 常時 |
| BR-34-05 | タイプ推測 | FormTypeGuesserによりエンティティのプロパティからフォームタイプを推測する | createBuilderForProperty使用時 |
| BR-34-06 | 送信済みチェック | 一度submitされたフォームへの再submit時はAlreadySubmittedExceptionをスローする | 既にsubmit済みのフォームへの再送信時 |

### 計算ロジック

特になし。

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

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

本機能自体はデータベース操作を行わない。

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| - | - | - | データベース操作なし |

### テーブル別操作詳細

該当なし。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | AlreadySubmittedException | 送信済みフォームへの再送信 | フォームの状態を確認する |
| - | LogicException | 未構築フォームへのアクセス | フォーム構築後にアクセスする |
| - | TransformationFailedException | データ変換失敗 | Transformerの実装を確認する |
| - | OutOfBoundsException | 存在しない子フォームへのアクセス | フォーム名を確認する |
| - | RuntimeException | 無効なフォーム操作 | 操作手順を確認する |

### リトライ仕様

リトライは不要（同期処理のため）。

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

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

## パフォーマンス要件

- ResolvedFormTypeによるフォームタイプの解決結果キャッシュ
- FormRegistryによるフォームタイプの登録と再利用
- LazyOptionの活用によるオプション評価の遅延

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

- CSRF保護が有効であることを確認する（デフォルトで有効）
- フォーム入力値のXSSフィルタリングは別途必要（Formコンポーネント自体はサニタイズしない）
- ファイルアップロードフォームではファイルタイプとサイズの制限を設定する

## 備考

- Formクラスは3層データ表現（model/normalized/view）を核とした設計であり、このアーキテクチャの理解がコンポーネントの理解に不可欠
- FormFlowは マルチステップフォームのサポート機能で、Symfony 8.1で追加された機能である
- Extension/Core/Typeディレクトリに多数の組み込みフォームタイプが定義されている

---

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

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

### 推奨読解順序

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

フォームの3層データ表現とフォームインターフェースを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | FormInterface.php | `src/Symfony/Component/Form/FormInterface.php` | フォームの公開インターフェース。getData, submit, createView等のメソッド定義 |
| 1-2 | FormView.php | `src/Symfony/Component/Form/FormView.php` | レンダリング用のフォームビューデータクラス |
| 1-3 | FormEvent.php | `src/Symfony/Component/Form/FormEvent.php` | フォームイベントの基底クラス |
| 1-4 | FormEvents.php | `src/Symfony/Component/Form/FormEvents.php` | イベント名の定数定義 |

**読解のコツ**: Form.phpのクラスコメント（33-66行目）で3層データ表現（model, normalized, view）の概念が詳しく説明されている。この理解がFormコンポーネント全体の理解の鍵となる。

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

フォーム生成の起点であるFormFactoryを確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | FormFactory.php | `src/Symfony/Component/Form/FormFactory.php` | フォーム生成のファクトリ。create, createNamed, createBuilder等 |
| 2-2 | FormRegistry.php | `src/Symfony/Component/Form/FormRegistry.php` | フォームタイプの登録・解決 |

**主要処理フロー**:
1. **30-33行目** (FormFactory.php): `create()` - createBuilder経由でフォーム生成
2. **51-54行目** (FormFactory.php): `createBuilder()` - FormRegistryからタイプ取得、ビルダー生成
3. **59-78行目** (FormFactory.php): `createNamedBuilder()` - タイプ解決、ビルダー生成、buildForm呼び出し
4. **80-120行目** (FormFactory.php): `createBuilderForProperty()` - TypeGuesserによるフォームタイプ推測

#### Step 3: フォーム本体を理解する

Formクラスのライフサイクルを確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | Form.php | `src/Symfony/Component/Form/Form.php` | フォーム本体。setData, submit, createViewのフロー |

**主要処理フロー**:
- **33-66行目**: 3層データ表現（model/normalized/view）の解説コメント
- setData(): PRE_SET_DATA -> ModelTransformer -> ViewTransformer -> POST_SET_DATA
- submit(): PRE_SUBMIT -> ViewTransformer::reverseTransform -> SUBMIT -> ModelTransformer::reverseTransform -> POST_SUBMIT

#### Step 4: データ変換を理解する

ModelTransformerとViewTransformerの仕組みを確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | DataTransformerInterface.php | `src/Symfony/Component/Form/DataTransformerInterface.php` | データ変換のインターフェース |
| 4-2 | CallbackTransformer.php | `src/Symfony/Component/Form/CallbackTransformer.php` | コールバックベースの変換器 |

#### Step 5: 組み込みフォームタイプを理解する

代表的なフォームタイプを確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | FormType.php | `src/Symfony/Component/Form/Extension/Core/Type/FormType.php` | 基本フォームタイプ |
| 5-2 | TextType.php | `src/Symfony/Component/Form/Extension/Core/Type/TextType.php` | テキストフィールド |

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

```
FormFactory::create()
    |
    +-- FormFactory::createBuilder()
    |       |
    |       +-- FormRegistry::getType() -> ResolvedFormType
    |       +-- ResolvedFormType::createBuilder() -> FormBuilder
    |       +-- ResolvedFormType::buildForm()
    |
    +-- FormBuilder::getForm() -> Form
            |
            +-- Form::setData()
            |       +-- PRE_SET_DATA event
            |       +-- ModelTransformer::transform()
            |       +-- ViewTransformer::transform()
            |       +-- POST_SET_DATA event
            |
            +-- Form::submit() / handleRequest()
            |       +-- PRE_SUBMIT event
            |       +-- ViewTransformer::reverseTransform()
            |       +-- SUBMIT event
            |       +-- ModelTransformer::reverseTransform()
            |       +-- POST_SUBMIT event
            |       +-- Validator integration
            |
            +-- Form::createView()
                    +-- ResolvedFormType::buildView()
                    +-- ResolvedFormType::finishView()
```

### データフロー図

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

エンティティ/DTO ─────> Form::setData()
                           |
                           v
                      ModelTransformer::transform()
                           |
                           v
                      ViewTransformer::transform()
                           |
                           v
                      FormView ─────────────────────> HTMLフォーム

HTTPリクエスト ────> Form::submit()
                           |
                           v
                      ViewTransformer::reverseTransform()
                           |
                           v
                      ModelTransformer::reverseTransform()
                           |
                           v
                      Validator::validate() ──────> エンティティ/DTO
                                                    (更新済み)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| Form.php | `src/Symfony/Component/Form/Form.php` | ソース | フォーム本体クラス |
| FormFactory.php | `src/Symfony/Component/Form/FormFactory.php` | ソース | フォームファクトリ |
| FormBuilder.php | `src/Symfony/Component/Form/FormBuilder.php` | ソース | フォームビルダー |
| FormRegistry.php | `src/Symfony/Component/Form/FormRegistry.php` | ソース | フォームタイプレジストリ |
| FormView.php | `src/Symfony/Component/Form/FormView.php` | ソース | フォームビュー |
| FormEvents.php | `src/Symfony/Component/Form/FormEvents.php` | ソース | イベント名定数 |
| FormConfigBuilder.php | `src/Symfony/Component/Form/FormConfigBuilder.php` | ソース | フォーム設定ビルダー |
| ResolvedFormType.php | `src/Symfony/Component/Form/ResolvedFormType.php` | ソース | 解決済みフォームタイプ |
| DataTransformerInterface.php | `src/Symfony/Component/Form/DataTransformerInterface.php` | ソース | データ変換インターフェース |
| Extension/Core/Type/ | `src/Symfony/Component/Form/Extension/Core/Type/` | ソース | 組み込みフォームタイプ群 |
| Extension/Validator/ | `src/Symfony/Component/Form/Extension/Validator/` | ソース | バリデーション拡張 |
| Flow/ | `src/Symfony/Component/Form/Flow/` | ソース | フォームフロー（マルチステップ） |
