# 画面設計書 6-検索サジェスト

## 概要

本ドキュメントは、Shopware 6 Storefrontにおける検索サジェストの画面設計書である。検索入力時にリアルタイムでオートコンプリート候補を表示するドロップダウンコンポーネントである。

### 本画面の処理概要

検索サジェストは、ヘッダーの検索バーに文字を入力すると自動的に表示されるドロップダウンである。入力されたキーワードに基づいて商品候補を即座に表示し、顧客の検索体験を向上させる。

**業務上の目的・背景**：検索サジェストは、顧客が検索キーワードを入力する際に候補を提示することで、入力の手間を軽減し、スペルミスによる検索失敗を防ぐ。また、関連商品の提案により、顧客が意図していなかった商品を発見する機会を提供し、クロスセル効果も期待できる。検索離脱率の低減とコンバージョン向上に寄与する重要な機能である。

**画面へのアクセス方法**：ヘッダーの検索バーに文字を入力すると自動的に表示される。AJAX経由で`/suggest`エンドポイントが呼び出される。

**主要な操作・処理内容**：
1. 入力キーワードに基づく商品検索（SuggestPageLoader）
2. 商品候補一覧の表示（画像、名前、価格）
3. 候補クリックで商品詳細への遷移
4. 「すべての結果を見る」で検索結果ページへ遷移

**画面遷移**：
- 遷移元：ヘッダー検索バー（自動表示）
- 遷移先：商品詳細ページ（候補クリック）、検索結果ページ（「すべての結果」クリック）

**権限による表示制御**：全ユーザーがアクセス可能。特別な権限制御なし。

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 33 | 検索サジェスト | 主機能 | 検索入力時のオートコンプリート（SearchController::suggest） |

## 画面種別

ドロップダウン / ウィジェット

## URL/ルーティング

| 項目 | 値 |
|------|-----|
| URL | `/suggest` |
| ルート名 | `frontend.search.suggest` |
| HTTPメソッド | GET |
| XmlHttpRequest | 必須 |

## 入出力項目

### 入力項目

| 項目名 | パラメータ名 | 必須 | 型 | 説明 |
|--------|-------------|------|-----|------|
| 検索キーワード | search | 必須 | string | 検索文字列 |

### 出力データ

| 項目名 | データソース | 説明 |
|--------|-------------|------|
| page | SuggestPageLoader | サジェスト用ページオブジェクト |
| page.searchResult | 検索結果 | 商品候補一覧 |
| page.searchTerm | リクエスト | 検索キーワード |

## 表示項目

| セクション | 表示項目 | 説明 |
|-----------|---------|------|
| リスト | 商品画像 | サムネイル画像 |
| リスト | 商品名 | 商品タイトル |
| リスト | バリエーション情報 | 色/サイズ等（設定による） |
| リスト | 価格 | 販売価格、参照価格 |
| フッター | 全結果リンク | 「すべての結果を見る（{件数}件）」 |
| 空状態 | メッセージ | 「結果が見つかりません」 |

## イベント仕様

### 1-サジェスト表示

検索バーに文字を入力すると、デバウンス処理後にAJAXリクエストが送信される。

**処理フロー**：
1. JavaScriptが入力イベントをキャッチ（デバウンス適用）
2. AJAX経由で`/suggest?search=キーワード`を呼び出し
3. SearchController::suggestが実行される
4. SuggestPageLoaderで商品検索（no-aggregationsフラグ付き）
5. SuggestPageLoadedHookを発火
6. search-suggest.html.twigでHTMLをレンダリング
7. ドロップダウンとして表示

### 2-商品候補クリック

商品候補をクリックすると、該当商品の詳細ページへ遷移する。

### 3-全結果リンククリック

「すべての結果を見る」をクリックすると、検索結果ページへ遷移する。

### 4-サジェスト非表示

検索バーからフォーカスが外れる、Escキー押下、検索実行でサジェストが閉じる。

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

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

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| サジェスト表示 | product | SELECT | 商品検索（軽量版） |

本画面は表示専用であり、データベースへの書き込み操作は発生しない。

## メッセージ仕様

| メッセージ種別 | 条件 | メッセージ内容 |
|--------------|------|--------------|
| 情報 | 検索結果0件 | 「検索結果がありません」（header.searchNoResult） |

## 例外処理

| 例外条件 | 対応 |
|---------|------|
| 検索キーワード空 | 空のレスポンスまたはサジェスト非表示 |
| AJAX通信エラー | サジェスト非表示、コンソールエラー |

## 備考

- パフォーマンス最適化のため、aggregations（集計）は取得しない（no-aggregationsフラグ）
- 入力のデバウンス処理によりリクエスト数を抑制
- バリエーション情報の表示は`core.listing.showVariantOptionInSearchSuggestionResult`設定による
- 商品画像がない場合はプレースホルダーアイコンを表示
- listboxロールでアクセシビリティに配慮

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | SuggestPage.php | `src/Storefront/Page/Suggest/SuggestPage.php` | ページオブジェクトの構造 |

**読解のコツ**: SuggestPageは軽量な検索結果を持ち、aggregationsは含まない。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | SearchController.php | `src/Storefront/Controller/SearchController.php` | suggestメソッド（71-88行目） |

**主要処理フロー**:
1. **77行目**: Routeアノテーションでエンドポイント定義
2. **79-81行目**: no-aggregationsフラグの設定
3. **83行目**: SuggestPageLoaderで検索実行
4. **85行目**: SuggestPageLoadedHookでフック処理
5. **87行目**: search-suggest.html.twigでレンダリング

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | search-suggest.html.twig | `src/Storefront/Resources/views/storefront/layout/header/search-suggest.html.twig` | サジェストテンプレート |

**主要処理フロー**:
- **7-10行目**: listboxロールとARIA属性
- **12-108行目**: 商品候補のループ表示
- **20-52行目**: 商品画像の表示（メディアタイプ分岐）
- **54-71行目**: 商品名とバリエーション
- **73-101行目**: 価格表示
- **111-145行目**: 結果件数と「すべての結果」リンク

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

```
[検索バー入力]
    |
    v
JavaScript (デバウンス + AJAX)
    |
    v
SearchController::suggest()
    |
    +-- [no-aggregations フラグ設定]
    |
    +-- SuggestPageLoader::load()
    |       |
    |       +-- ProductSearchRoute::load() (軽量版)
    |
    +-- SuggestPageLoadedHook
    |
    +-- renderStorefront()
            +-- search-suggest.html.twig
                    |
                    v
            [ドロップダウン表示]
```

### データフロー図

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

search=キーワード  -->  SearchController::suggest()
(AJAX, debounced)            |
                            v
                   SuggestPageLoader
                            |
                            +-- no-aggregations
                            |
                            v
                   ProductSearchRoute
                            |
                            v
                   SuggestPage            -->  HTML Fragment
                            |
                            v
                   search-suggest.html.twig
                            |
                            v
                   [Dropdown]
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| SearchController.php | `src/Storefront/Controller/SearchController.php` | コントローラー | ルーティングエントリーポイント |
| SuggestPageLoader.php | `src/Storefront/Page/Suggest/SuggestPageLoader.php` | ページローダー | ページデータの構築 |
| SuggestPage.php | `src/Storefront/Page/Suggest/SuggestPage.php` | データ構造 | ページオブジェクト定義 |
| search-suggest.html.twig | `src/Storefront/Resources/views/storefront/layout/header/search-suggest.html.twig` | テンプレート | サジェストHTML |
| search.html.twig | `src/Storefront/Resources/views/storefront/layout/header/search.html.twig` | テンプレート | 検索バー |
