# 画面設計書 19-イベントパネル

## 概要

本ドキュメントは、Symfony WebProfilerBundleが提供する「イベントパネル」画面の設計書である。リクエスト処理中にディスパッチされたイベントの一覧を表示するプロファイラーのコレクターパネルを定義する。

### 本画面の処理概要

**業務上の目的・背景**：Symfonyのイベント駆動アーキテクチャにおいて、どのイベントがディスパッチされ、どのリスナーが呼び出されたかを確認することは、アプリケーションの動作理解やデバッグに不可欠である。本パネルは、EventDataCollectorが収集したイベント情報を「呼び出されたリスナー」「呼び出されなかったリスナー」「オーファンイベント（リスナーなしのイベント）」に分類して表示する。複数のイベントディスパッチャーがある場合はタブで切り替えて表示する。

**画面へのアクセス方法**：プロファイラーパネル画面の左サイドメニューから「Events」を選択してアクセスする。

**主要な操作・処理内容**：
1. ディスパッチャー別のイベント確認 -- 複数のイベントディスパッチャーをタブで切替
2. 呼び出されたリスナーの確認 -- イベント名ごとにグループ化された呼び出し済みリスナーの一覧（優先度付き）
3. 呼び出されなかったリスナーの確認 -- 登録されているが今回のリクエストでは呼び出されなかったリスナー
4. オーファンイベントの確認 -- ディスパッチされたがリスナーが存在しなかったイベント

**画面遷移**：
- 遷移元：プロファイラーパネルのメニュー選択
- 遷移先：プロファイラーの他パネルへの遷移

**権限による表示制御**：開発環境でのみ利用可能。

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 63 | WebProfilerBundle | 主機能 | ディスパッチされたイベントの一覧を表示するパネル |
| 12 | EventDispatcher | 主機能 | EventDispatcherコンポーネントで記録されたイベント情報の表示 |
| 2 | HttpKernel | 補助機能 | EventDataCollectorによるイベントデータの収集 |

## 画面種別

一覧（コレクターパネル）

## URL/ルーティング

| ルート名 | URL | コントローラー |
|---------|-----|--------------|
| _profiler | `/_profiler/{token}?panel=events` | `web_profiler.controller.profiler::panelAction` |

## 入出力項目

| 項目名 | 種別 | 型 | 説明 |
|--------|------|-----|------|
| token | 入力（URLパラメータ） | string | プロファイラートークン |
| panel | 入力（クエリパラメータ） | string | "events"固定 |
| collector | テンプレート変数 | EventDataCollector | イベントデータコレクター |

## 表示項目

### パネル表示

| 表示項目 | データソース | 表示形式 | 説明 |
|----------|-------------|---------|------|
| ディスパッチャー名タブ | collector.data | タブ群 | ディスパッチャーごとのタブ切替 |
| Called Listenersタブ | dispatcherData['called_listeners'] | テーブル | 呼び出されたリスナー一覧（バッジ付きカウント） |
| Not Called Listenersタブ | dispatcherData['not_called_listeners'] | テーブル | 呼び出されなかったリスナー一覧 |
| Orphaned Eventsタブ | dispatcherData['orphaned_events'] | テーブル | オーファンイベント一覧 |

### リスナーテーブル

| カラム | データソース | 説明 |
|--------|-------------|------|
| Priority | listener.priority | リスナーの優先度（右寄せ） |
| Listener | listener.stub | リスナーの詳細（profiler_dumpで表示） |
| Event | listener.event | イベント名（グループヘッダーとして表示） |

## イベント仕様

### 1-ディスパッチャータブ切替

複数のイベントディスパッチャーが存在する場合、タブをクリックして切り替える。sf-tabsクラスによるタブ切替。

### 2-リスナー種別タブ切替

Called Listeners / Not Called Listeners / Orphaned Eventsのタブをクリックして表示を切り替える。各タブにバッジでアイテム数が表示される。

## データベース更新仕様

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

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| - | - | - | 本画面はデータベース操作を行わない |

## メッセージ仕様

| メッセージ種別 | メッセージ内容 | 表示条件 |
|--------------|--------------|---------|
| 情報 | "No events have been recorded. Check that debugging is enabled in the kernel." | 呼び出されたリスナーがない場合 |
| 情報 | "There are no uncalled listeners." | 呼び出されなかったリスナーがない場合 |
| 情報 | "There are no orphaned events." | オーファンイベントがない場合 |

## 例外処理

プロファイラーパネル共通の例外処理に準ずる。

## 備考

- リスナーテーブルはrender_tableマクロ（92-126行目）で生成される
- イベント名をグループヘッダー（tbodyのth要素）として表示し、同一イベントのリスナーをグループ化
- profiler_dump()関数でリスナーのstub情報をダンプ表示（クラス名、メソッド名等が展開可能）
- ツールバーブロックは定義されていない（`toolbar`ブロックは空ではなくそもそも未定義=layout.html.twigのデフォルト使用）

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | events.html.twig | `src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/events.html.twig` | collector.dataの構造：ディスパッチャー名をキーとし、各値にcalled_listeners, not_called_listeners, orphaned_eventsを持つ |

**読解のコツ**: render_tableマクロ（92-126行目）のlistenersパラメータの使い方からリスナーの構造（event, priority, stub）が分かる。

#### Step 2: テンプレート構造を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | events.html.twig | `src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/events.html.twig` | `menu`ブロック（3-8行目）、`panel`ブロック（10-90行目）、`render_table`マクロ（92-126行目） |

**主要処理フロー**:
- **14行目**: collector.dataをループしてディスパッチャーごとのタブを生成
- **23-30行目**: Called Listenersタブ
- **32-50行目**: Not Called Listenersタブ
- **52-83行目**: Orphaned Eventsタブ
- **101行目**: イベント名でグループ化（previous_event変数で切り替え判定）

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

```
GET /_profiler/{token}?panel=events
    |
    +-- ProfilerController::panelAction()
            |
            +-- Twig::render(events.html.twig)
                    |
                    +-- extends layout.html.twig
                    |
                    +-- panel ブロック
                    |       +-- ディスパッチャータブ（sf-tabs）
                    |               +-- Called Listeners タブ
                    |               |       +-- render_table マクロ
                    |               +-- Not Called Listeners タブ
                    |               |       +-- render_table マクロ
                    |               +-- Orphaned Events タブ
                    |
                    +-- render_table マクロ
                            +-- profiler_dump(listener.stub)
```

### データフロー図

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

token (URL)          ProfilerController              events.html.twig
panel=events    -->  ::panelAction()             -->  (イベントパネル)
                          |
                     EventDataCollector.data
                     {
                       dispatcher_name: {
                         called_listeners: [{event, priority, stub}...],
                         not_called_listeners: [...],
                         orphaned_events: [event_name...]
                       }
                     }
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| ProfilerController.php | `src/Symfony/Bundle/WebProfilerBundle/Controller/ProfilerController.php` | ソース | panelActionメソッド |
| events.html.twig | `src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/events.html.twig` | テンプレート | イベントパネルHTML |
| layout.html.twig | `src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/layout.html.twig` | テンプレート | パネル共通レイアウト |
