# 機能設計書 63-WebProfilerBundle

## 概要

本ドキュメントは、Symfony WebProfilerBundleの機能設計書である。WebProfilerBundleは、リクエスト実行の詳細情報を表示する開発ツール（Web Debug Toolbar、Profilerパネル）を提供する。

### 本機能の処理概要

WebProfilerBundleは、Symfonyアプリケーションのリクエスト/レスポンス処理に関する詳細なプロファイリング情報を視覚的に表示するバンドルである。Web Debug Toolbar（WDT）とProfilerパネルUIを提供し、各DataCollectorから収集した情報を開発者に提示する。

**業務上の目的・背景**：Web開発において、リクエスト処理の各段階（ルーティング、コントローラー実行、テンプレートレンダリング、DB操作等）の詳細を把握することは、パフォーマンス最適化やバグ修正に不可欠である。WebProfilerBundleは、これらの情報を統一的なUIで提供する。

**機能の利用シーン**：開発環境でHTMLレスポンスの画面下部に表示されるWeb Debug Toolbarから各種情報にアクセスする。プロファイラーパネルでは過去のリクエストの検索、パフォーマンスタイムライン、例外情報、ログ、ルーティング情報等を確認できる。

**主要な処理内容**：
1. ProfilerControllerによるプロファイラーUI画面群の提供（ホーム、パネル、検索、検索結果）
2. Web Debug Toolbarのレンダリング（toolbar.html.twig）
3. 各DataCollector用テンプレートのホスティング
4. RouterControllerによるURLマッチングトレース表示
5. ExceptionPanelControllerによる例外詳細表示
6. CSP（Content Security Policy）対応のnonce管理
7. ソースファイル表示、phpinfo()、xdebug_info()の出力

**関連システム・外部連携**：HttpKernelのProfilerサービス、各種DataCollector、TwigBundle、Routingコンポーネント

**権限による制御**：本番環境（kernel.environment='prod'）での使用時にE_USER_WARNING警告を発生させる（WebProfilerBundle.php 23-25行目）。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 1 | プロファイラーホーム | 主機能 | ProfilerController::homeActionによるホーム画面 |
| 2 | プロファイラーパネル | 主機能 | ProfilerController::panelActionによるパネル表示 |
| 3 | プロファイラー検索 | 主機能 | ProfilerController::searchActionによる検索実行 |
| 4 | プロファイラー検索バー | 主機能 | ProfilerController::searchBarActionによる検索フォーム |
| 5 | プロファイラー検索結果 | 主機能 | ProfilerController::searchResultsActionによる結果表示 |
| 6 | プロファイラー情報 | 主機能 | トークン不明時のinfo.html.twig表示 |
| 7 | ソースファイル表示 | 主機能 | ProfilerController::openActionによるソース表示 |
| 8 | PHP情報表示 | 主機能 | ProfilerController::phpinfoActionによるphpinfo()出力 |
| 9 | Xdebug情報表示 | 主機能 | ProfilerController::xdebugActionによるxdebug_info()出力 |
| 10 | プロファイラー設定 | 主機能 | テーマ設定モーダル画面 |
| 11 | リダイレクトインターセプト | 主機能 | リダイレクト先URL表示 |
| 12 | Webデバッグツールバー | 主機能 | ProfilerController::toolbarActionによるWDT |
| 13 | ツールバースタイルシート | 主機能 | toolbarStylesheetActionによるCSS出力 |
| 14-34 | 各種パネル | 主機能 | DataCollector別の情報表示パネル |
| 35 | 設定パネル | 主機能 | Symfony設定・環境情報パネル |
| 36 | コマンドパネル | 主機能 | コンソールコマンド実行情報パネル |

## 機能種別

開発ツール / プロファイリング / デバッグUI

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| token | string | Yes | プロファイルトークン | Profilerから取得可能なトークン |
| panel | string | No | 表示するパネル名 | 登録済みDataCollector名 |
| page | string | No | ページ種別 | デフォルト: home |
| type | string | No | プロファイルタイプ | デフォルト: request |
| ip | string | No | 検索条件: IPアドレス | - |
| method | string | No | 検索条件: HTTPメソッド | - |
| status_code | string | No | 検索条件: ステータスコード | - |
| url | string | No | 検索条件: URL | - |
| start | string | No | 検索条件: 開始日時 | - |
| end | string | No | 検索条件: 終了日時 | - |
| limit | int | No | 検索結果件数制限 | - |

### 入力データソース

- HTTPリクエストパラメータ（クエリストリング）
- Profilerサービスに保存されたプロファイルデータ
- Sessionに保存された検索条件

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| HTML レスポンス | Response | プロファイラー画面のHTML |
| CSS レスポンス | Response | ツールバースタイルシート |
| フォントファイル | BinaryFileResponse | JetBrainsMono.woff2 |

### 出力先

HTMLレスポンスとしてWebブラウザに表示

## 処理フロー

### 処理シーケンス

```
1. リクエスト受信（プロファイラーURL）
   └─ Routingにより適切なコントローラーアクションへ
2. プロファイル読み込み
   └─ Profiler::loadProfile($token) でプロファイルデータ取得
3. テンプレート選択
   └─ TemplateManagerでパネルに対応するテンプレートを特定
4. CSP nonce生成
   └─ ContentSecurityPolicyHandler でnonce値を生成
5. テンプレートレンダリング
   └─ Twig::render() でHTML生成
6. レスポンス返却
```

### フローチャート

```mermaid
flowchart TD
    A[リクエスト受信] --> B{アクション判定}
    B -->|home| C[最新プロファイルにリダイレクト]
    B -->|panel| D[Profiler.loadProfile]
    B -->|search| E[検索条件をSessionに保存]
    B -->|searchResults| F[Profiler.find実行]
    B -->|toolbar| G[ツールバーレンダリング]
    D --> H{プロファイル存在?}
    H -->|No| I[info.html.twig表示]
    H -->|Yes| J[TemplateManager.getName]
    J --> K[renderWithCspNonces]
    K --> L[Response返却]
    E --> M[検索結果にリダイレクト]
    F --> K
    G --> K
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | 本番環境警告 | prod環境でE_USER_WARNING発生 | boot時 |
| BR-02 | Profiler無効時404 | Profilerがnullの場合NotFoundHttpException | 各アクション実行時 |
| BR-03 | 例外パネル優先表示 | ExceptionDataCollectorに例外がある場合、そのパネルを自動選択 | panelAction（panel未指定時） |
| BR-04 | Dumpパネル優先表示 | DumpDataCollectorにダンプがある場合、そのパネルを自動選択 | panelAction（panel未指定、例外なし時） |
| BR-05 | latest トークン解決 | token='latest'の場合、最新プロファイルのトークンに置換 | panelAction |
| BR-06 | 検索条件Session保存 | 検索条件をSessionに保存し、再表示時に復元 | searchAction |

### 計算ロジック

特になし。

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| プロファイル検索 | Profilerストレージ | SELECT | Profiler::find()によるプロファイル検索 |
| プロファイル読込 | Profilerストレージ | SELECT | Profiler::loadProfile()によるプロファイルデータ取得 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| 404 | NotFoundHttpException | Profilerが無効 | 有効化が必要 |
| 404 | NotFoundHttpException | 指定パネルが存在しない | 正しいパネル名を指定 |
| 404 | NotFoundHttpException | ソースファイルの不正パス | パスの検証 |
| 404 | NotFoundHttpException | xdebugが未インストール | Xdebug 3のインストールが必要 |

### リトライ仕様

該当なし。

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

該当なし。

## パフォーマンス要件

- ツールバーCSS出力にはmax-age=600のCache-Controlヘッダーが設定される（ProfilerController 181行目）
- Profiler::disable()がアクション実行前に呼ばれ、プロファイラー自体のプロファイリングを防止

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

- ContentSecurityPolicyHandlerによりCSP nonceを生成し、スクリプト/スタイルのインジェクション対策
- openActionでは相対パスの'..'を含むパスやベースディレクトリ外のファイルアクセスを防止（391行目）
- 本番環境での使用は非推奨（E_USER_WARNING）

## 備考

- profiler_markup_version=3（Symfony 6.2+のプロファイラーUI）
- JetBrainsMono.woff2フォントを内蔵

---

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

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

### 推奨読解順序

#### Step 1: バンドル構造を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | WebProfilerBundle.php | `src/Symfony/Bundle/WebProfilerBundle/WebProfilerBundle.php` | boot()での本番環境警告 |

#### Step 2: コントローラーを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | ProfilerController.php | `src/Symfony/Bundle/WebProfilerBundle/Controller/ProfilerController.php` | メインコントローラー |
| 2-2 | RouterController.php | `src/Symfony/Bundle/WebProfilerBundle/Controller/RouterController.php` | ルーティングトレース |
| 2-3 | ExceptionPanelController.php | `src/Symfony/Bundle/WebProfilerBundle/Controller/ExceptionPanelController.php` | 例外パネル |

**主要処理フロー（ProfilerController）**:
- **53-58行目**: homeAction - 最新プロファイル検索結果へのリダイレクト
- **65-117行目**: panelAction - プロファイルパネル表示、パネル自動選択ロジック含む
- **124-163行目**: toolbarAction - WDTレンダリング、FlashBag保持処理含む
- **264-309行目**: searchAction - 検索条件のSession保存とリダイレクト
- **378-400行目**: openAction - ソースファイル表示（パス検証付き）

#### Step 3: CSPハンドリングを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | ContentSecurityPolicyHandler.php | `src/Symfony/Bundle/WebProfilerBundle/Csp/ContentSecurityPolicyHandler.php` | CSP nonce生成・管理 |

#### Step 4: テンプレート管理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | TemplateManager.php | `src/Symfony/Bundle/WebProfilerBundle/Profiler/TemplateManager.php` | パネルテンプレート名解決 |

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

```
ProfilerController
    │
    ├─ homeAction()
    │      └─ UrlGenerator::generate('_profiler_search_results')
    │
    ├─ panelAction($token)
    │      ├─ Profiler::loadProfile($token)
    │      ├─ TemplateManager::getName($profile, $panel)
    │      └─ renderWithCspNonces()
    │             ├─ ContentSecurityPolicyHandler::getNonces()
    │             └─ Twig::render()
    │
    ├─ toolbarAction($token)
    │      ├─ Profiler::loadProfile($token)
    │      └─ renderWithCspNonces('@WebProfiler/Profiler/toolbar.html.twig')
    │
    ├─ searchAction()
    │      ├─ Session::set() [検索条件保存]
    │      ├─ Profiler::find()
    │      └─ RedirectResponse
    │
    └─ searchResultsAction($token)
           ├─ Profiler::find()
           └─ renderWithCspNonces('@WebProfiler/Profiler/results.html.twig')
```

### データフロー図

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

HTTPリクエスト  ───▶  ProfilerController          ───▶  HTML Response
(token, panel)        │                                  (CSP nonces付き)
                      ├─ Profiler::loadProfile()
                      │      └─ Profile データ
                      ├─ TemplateManager
                      │      └─ テンプレート名解決
                      └─ Twig::render()
                             └─ HTML生成
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| WebProfilerBundle.php | `src/Symfony/Bundle/WebProfilerBundle/WebProfilerBundle.php` | ソース | バンドルクラス |
| ProfilerController.php | `src/Symfony/Bundle/WebProfilerBundle/Controller/ProfilerController.php` | ソース | メインコントローラー |
| RouterController.php | `src/Symfony/Bundle/WebProfilerBundle/Controller/RouterController.php` | ソース | ルーティングトレース |
| ExceptionPanelController.php | `src/Symfony/Bundle/WebProfilerBundle/Controller/ExceptionPanelController.php` | ソース | 例外パネル |
| ContentSecurityPolicyHandler.php | `src/Symfony/Bundle/WebProfilerBundle/Csp/ContentSecurityPolicyHandler.php` | ソース | CSP対応 |
| TemplateManager.php | `src/Symfony/Bundle/WebProfilerBundle/Profiler/TemplateManager.php` | ソース | テンプレート管理 |
| WebDebugToolbarListener.php | `src/Symfony/Bundle/WebProfilerBundle/EventListener/WebDebugToolbarListener.php` | ソース | WDT HTMLインジェクション |
| toolbar.html.twig | `src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/toolbar.html.twig` | テンプレート | ツールバーテンプレート |
| layout.html.twig | `src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/layout.html.twig` | テンプレート | プロファイラーレイアウト |
| search.html.twig | `src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/search.html.twig` | テンプレート | 検索フォーム |
| results.html.twig | `src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/results.html.twig` | テンプレート | 検索結果 |
