# 機能設計書 3-Routing

## 概要

本ドキュメントは、Symfony Routingコンポーネントの機能設計を記述する。RoutingはHTTPリクエストを設定変数のセットにマッピングするルーティング機能を提供し、URLパターンマッチング、ルート生成、URLジェネレーターを含む。

### 本機能の処理概要

Routingコンポーネントは、受信したHTTPリクエストのURLを解析し、対応するコントローラーとパラメータの組み合わせに変換する（マッチング）。また逆に、ルート名とパラメータからURLを生成する（ジェネレーション）。この双方向マッピングがWebアプリケーションのナビゲーション基盤を構成する。

**業務上の目的・背景**：Webアプリケーションでは、URLとアプリケーション内部の処理を対応付ける必要がある。Routingコンポーネントは宣言的なルート定義により、URLの設計とアプリケーション構造を分離し、SEOフレンドリーなURL設計や多言語対応、APIバージョニング等を実現する。

**機能の利用シーン**：全HTTPリクエスト処理においてkernel.requestイベントリスナーとして動作し、URLからコントローラーを特定する。テンプレートやコントローラー内でのURL生成（path(), url()関数）にも利用される。APIルーティング、リダイレクト管理、プロファイラーURL生成等にも活用される。

**主要な処理内容**：
1. ルート定義の読み込み（アノテーション/属性、YAML、XML、PHP）
2. URLパターンとHTTPリクエストのマッチング
3. ルート名とパラメータからのURL生成
4. ルートのコンパイル（正規表現生成）
5. マッチャー/ジェネレーターのキャッシュ（コンパイル済みPHPコード生成）
6. リクエストコンテキスト管理（ホスト、スキーム、ポート等）
7. 要件定義（パラメータの正規表現制約）
8. 条件式によるルートマッチング制御

**関連システム・外部連携**：HttpKernel（kernel.requestイベントでマッチング実行）、HttpFoundation（Requestオブジェクトとの連携）、Config（ルート設定ファイルの読み込み）、ExpressionLanguage（条件式評価）

**権限による制御**：ルート定義にsecurity属性を指定することで、SecurityコンポーネントのIsGranted等と連携したアクセス制御が可能。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 1 | プロファイラーホーム | 主機能 | 最新プロファイル検索結果へのリダイレクトURLをRouting（UrlGenerator）で生成する |
| 3 | プロファイラー検索 | 主機能 | 検索条件を基にRouting（UrlGenerator）で検索結果画面へのリダイレクトURLを生成する |
| 12 | Webデバッグツールバー | 補助機能 | Routing（UrlGenerator）によるプロファイラーパネルへのリンクURL生成 |
| 20 | ルーティングパネル | 主機能 | Routingコンポーネントによるルートマッチング結果の表示 |
| 21 | ルーター詳細パネル | 主機能 | TraceableUrlMatcherによるルーティングトレース情報の生成・表示 |
| 42 | リダイレクト | 主機能 | Routing（UrlGenerator）による指定ルート名からのURLを生成してリダイレクト |

## 機能種別

URLマッピング / パターンマッチング / URL生成

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| pathinfo | string | Yes | リクエストパス（例: /blog/2024/hello） | UTF-8文字列 |
| host | string | No | リクエストホスト名 | ホスト名パターンマッチ |
| method | string | No | HTTPメソッド | GET/POST/PUT/DELETE等 |
| scheme | string | No | URLスキーム（http/https） | http/https |
| route_name | string | Yes(生成時) | URL生成時のルート名 | 登録済みルート名 |
| parameters | array | No | URL生成時のパラメータ | ルート要件に合致 |

### 入力データソース

- ルート定義ファイル（YAML/XML/PHP/アノテーション/属性）
- HttpFoundation Requestオブジェクト
- URL生成時のルート名とパラメータ

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| _controller | string | マッチしたコントローラー（例: App\Controller\BlogController::show） |
| _route | string | マッチしたルート名 |
| パラメータ群 | array | URLから抽出されたパラメータ（例: ['slug' => 'hello']） |
| 生成URL | string | URL生成時の結果URL |

### 出力先

- Request::$attributesプロパティに設定（マッチング時）
- 文字列としてURL返却（生成時）

## 処理フロー

### 処理シーケンス

```
1. ルート定義読み込み
   └─ LoaderInterface経由でルートファイルをRouteCollectionに変換
2. ルートコンパイル
   └─ RouteCompilerが各ルートを正規表現にコンパイル
3. マッチャー/ジェネレーター生成
   └─ ダンパーがPHPコードを生成しキャッシュ
4. URLマッチング（リクエスト受信時）
   └─ CompiledUrlMatcherが正規表現でパスをマッチ
5. URL生成（テンプレート/コントローラー内）
   └─ CompiledUrlGeneratorがルート名からURLを組み立て
```

### フローチャート

```mermaid
flowchart TD
    A[HTTPリクエスト受信] --> B[RequestContext設定]
    B --> C[CompiledUrlMatcher::match]
    C --> D{マッチ成功?}
    D -->|Yes| E[パラメータ抽出]
    D -->|No| F[ResourceNotFoundException]
    E --> G[Request::attributesに設定]
    G --> H[コントローラー実行へ]

    I[URL生成リクエスト] --> J[CompiledUrlGenerator::generate]
    J --> K{ルート存在?}
    K -->|Yes| L[パラメータ置換・URL組み立て]
    K -->|No| M[RouteNotFoundException]
    L --> N[URL文字列返却]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | ルート優先順序 | ルートは定義順に評価され、最初にマッチしたルートが採用される | URLマッチング時 |
| BR-02 | スキーム強制 | httpsスキームが要求されるルートにhttpでアクセスした場合、リダイレクトが発生する | ルートにschemes制約がある場合 |
| BR-03 | メソッド制約 | ルートにHTTPメソッド制約がある場合、不一致のメソッドはMethodNotAllowedExceptionとなる | ルートにmethods制約がある場合 |
| BR-04 | strict_requirements | URL生成時にパラメータがルート要件を満たさない場合の動作を制御 | strict_requirementsオプション設定時 |
| BR-05 | 条件式評価 | ルートにcondition属性がある場合、ExpressionLanguageで評価される | condition設定時 |

### 計算ロジック

- ルートコンパイル：URLパターンを正規表現に変換する。`{parameter}`記法を`(?P<parameter>[^/]++)`等の正規表現グループに変換する。

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

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

Routingコンポーネントはデータベース操作を行わない。ルート定義のキャッシュはファイルシステムに格納される。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | ResourceNotFoundException | URLにマッチするルートが見つからない | ルート定義の確認 |
| - | MethodNotAllowedException | URLはマッチするがHTTPメソッドが不一致 | 許可メソッドの確認 |
| - | RouteNotFoundException | URL生成時に指定ルート名が存在しない | ルート名の確認 |
| - | MissingMandatoryParametersException | URL生成時に必須パラメータが不足 | パラメータの確認 |
| - | InvalidParameterException | URL生成時にパラメータが要件を満たさない | パラメータ値の確認 |

### リトライ仕様

リトライ機能なし。

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

トランザクション管理なし。

## パフォーマンス要件

- コンパイル済みマッチャー/ジェネレーターをPHPコードとしてキャッシュし、実行時のオーバーヘッドを最小化
- 大量ルート（1000+）でも効率的にマッチングできるよう、静的プレフィックスによるルートグルーピングを使用
- キャッシュディレクトリが設定されている場合、初回リクエスト後はコンパイル済みコードを再利用

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

- ルート定義にsecurity条件を設定可能
- URL生成時のパラメータはURLエンコードされる
- ホスト名ベースのルーティングではホスト名パターンのバリデーションが行われる

## 備考

- PHP 8属性（`#[Route]`）によるルート定義をサポート
- 国際化ルート（ロケール付きルート）に対応
- ExpressionLanguageによる高度な条件式マッチングが可能

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | Route.php | `src/Symfony/Component/Routing/Route.php` | ルート1つ分のデータ構造（path, host, schemes, methods, defaults, requirements, options, condition） |
| 1-2 | RouteCollection.php | `src/Symfony/Component/Routing/RouteCollection.php` | ルートの集合管理。add(), addPrefix(), addResource()等 |
| 1-3 | CompiledRoute.php | `src/Symfony/Component/Routing/CompiledRoute.php` | コンパイル後のルート情報（正規表現、変数、トークン） |
| 1-4 | RequestContext.php | `src/Symfony/Component/Routing/RequestContext.php` | マッチング/生成時のリクエストコンテキスト（ホスト、スキーム、ポート等） |

**読解のコツ**: Route.phpの行22-30でルートの全属性（path, host, schemes, methods, defaults, requirements, options, condition, compiled）が定義されている。これがルーティングのデータモデルの全体像である。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | Router.php | `src/Symfony/Component/Routing/Router.php` | マッチング/生成の統合エントリーポイント |

**主要処理フロー**:
1. **38行目**: RouterInterfaceとRequestMatcherInterfaceを実装
2. **55-65行目**: コンストラクタ。Loader、resource、options、RequestContextの設定
3. **84-95行目**: setOptions()。cache_dir、debug、generator_class、matcher_class等の設定

#### Step 3: マッチング処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | Matcher/CompiledUrlMatcher.php | `src/Symfony/Component/Routing/Matcher/CompiledUrlMatcher.php` | コンパイル済み正規表現によるURL照合 |
| 3-2 | Matcher/Dumper/CompiledUrlMatcherDumper.php | `src/Symfony/Component/Routing/Matcher/Dumper/CompiledUrlMatcherDumper.php` | マッチャーのPHPコード生成 |

#### Step 4: URL生成処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | Generator/CompiledUrlGenerator.php | `src/Symfony/Component/Routing/Generator/CompiledUrlGenerator.php` | コンパイル済みデータからのURL生成 |
| 4-2 | Generator/Dumper/CompiledUrlGeneratorDumper.php | `src/Symfony/Component/Routing/Generator/Dumper/CompiledUrlGeneratorDumper.php` | ジェネレーターのPHPコード生成 |

#### Step 5: ルートコンパイルを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | RouteCompiler.php | `src/Symfony/Component/Routing/RouteCompiler.php` | URLパターンから正規表現への変換ロジック |

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

```
Router::match($pathinfo) / Router::matchRequest($request)
    |
    +-- Router::getMatcher()
    |       +-- CompiledUrlMatcherDumper::getCompiledRoutes() [初回のみ]
    |       +-- new CompiledUrlMatcher(compiledRoutes, RequestContext)
    |
    +-- CompiledUrlMatcher::match($pathinfo)
            +-- 正規表現マッチング
            +-- パラメータ抽出

Router::generate($name, $parameters, $referenceType)
    |
    +-- Router::getGenerator()
    |       +-- CompiledUrlGeneratorDumper::getCompiledRoutes() [初回のみ]
    |       +-- new CompiledUrlGenerator(compiledRoutes, RequestContext)
    |
    +-- CompiledUrlGenerator::generate($name, $parameters, $referenceType)
            +-- パラメータ置換
            +-- URL組み立て
```

### データフロー図

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

ルート定義ファイル     --->  Loader::load()               --->  RouteCollection
(YAML/XML/PHP/属性)          RouteCompiler::compile()           CompiledRoute群

HTTPリクエスト         --->  CompiledUrlMatcher::match()  --->  ['_controller', '_route', params]
(pathinfo, host,              正規表現マッチング
 method, scheme)

ルート名 + パラメータ  --->  CompiledUrlGenerator         --->  URL文字列
                              ::generate()
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| Router.php | `src/Symfony/Component/Routing/Router.php` | ソース | マッチング/生成の統合クラス |
| Route.php | `src/Symfony/Component/Routing/Route.php` | ソース | ルート定義データ構造 |
| RouteCollection.php | `src/Symfony/Component/Routing/RouteCollection.php` | ソース | ルート集合管理 |
| RouteCompiler.php | `src/Symfony/Component/Routing/RouteCompiler.php` | ソース | ルートコンパイラ |
| CompiledRoute.php | `src/Symfony/Component/Routing/CompiledRoute.php` | ソース | コンパイル済みルート |
| RequestContext.php | `src/Symfony/Component/Routing/RequestContext.php` | ソース | リクエストコンテキスト |
| Matcher/ | `src/Symfony/Component/Routing/Matcher/` | ソース | URLマッチャー群 |
| Generator/ | `src/Symfony/Component/Routing/Generator/` | ソース | URLジェネレーター群 |
| Loader/ | `src/Symfony/Component/Routing/Loader/` | ソース | ルート定義ローダー群 |
| Attribute/ | `src/Symfony/Component/Routing/Attribute/` | ソース | PHP属性によるルート定義 |
| Requirement/ | `src/Symfony/Component/Routing/Requirement/` | ソース | 組み込みパラメータ要件 |
| Alias.php | `src/Symfony/Component/Routing/Alias.php` | ソース | ルートエイリアス |
| Exception/ | `src/Symfony/Component/Routing/Exception/` | ソース | ルーティング例外群 |
| DependencyInjection/ | `src/Symfony/Component/Routing/DependencyInjection/` | ソース | DI統合コンパイラパス |
