# 機能設計書 63-ランディングページ表示

## 概要

本ドキュメントは、Shopware Storefrontにおけるランディングページを表示する機能について、その処理内容、入出力仕様、およびコード構造を記述した機能設計書である。

### 本機能の処理概要

本機能は、マーケティングキャンペーンや特別プロモーション用に作成されたランディングページをストアフロントで表示する機能を提供する。

**業務上の目的・背景**：ECサイトでは、季節キャンペーン、新商品発売、セール告知など、通常のカテゴリ構造とは独立したプロモーション用ページが必要となる。ランディングページ機能により、CMSで作成したレイアウトを独立したURLで公開し、広告やメールマガジンからの誘導先として活用できる。SEO対策としてメタ情報の個別設定も可能。

**機能の利用シーン**：
- 広告キャンペーンのクリック先として専用ページを表示
- メールマガジンからの特別オファーページを表示
- 季節イベント（セール、クリスマス等）の特設ページ表示
- 新商品・新ブランドの紹介ページ表示

**主要な処理内容**：
1. ランディングページIDをURLパラメータから取得
2. Store API経由でランディングページデータを取得
3. 紐付けられたCMSページを解決
4. メタ情報（タイトル、説明、キーワード）を設定
5. Twigテンプレートでレンダリング

**関連システム・外部連携**：Store APIのLandingPageRoute、GenericPageLoader

**権限による制御**：公開ページは認証不要。アクティブフラグで公開制御

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 44 | ランディングページ | 主機能 | ランディングページの作成・管理 |

## 機能種別

データ連携 / 画面表示

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| landingPageId | string | Yes | ランディングページのUUID | 有効なUUID形式 |
| request | Request | Yes | HTTPリクエストオブジェクト | - |
| context | SalesChannelContext | Yes | 販売チャネルコンテキスト | - |

### 入力データソース

- リクエストURL: `/landingPage/{landingPageId}` からランディングページIDを取得
- Store API: AbstractLandingPageRoute
- データベース: landing_page、cms_page各テーブル

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| page | LandingPage | ランディングページオブジェクト |
| page.landingPage | LandingPageEntity | ランディングページエンティティ |
| page.landingPage.cmsPage | CmsPageEntity | 紐付けられたCMSページ |
| page.metaInformation | MetaInformation | SEO用メタ情報 |

### 出力先

HTMLレスポンス（Twigテンプレート `@Storefront/storefront/page/content/index.html.twig` によるレンダリング）

## 処理フロー

### 処理シーケンス

```
1. LandingPageController::index() がリクエストを受信
   └─ ルート: /landingPage/{landingPageId}

2. パラメータのバリデーション
   └─ landingPageId が必須

3. LandingPageLoader::load() を呼び出し
   └─ Store API経由でランディングページを取得

4. CMSページの確認
   └─ CMSページが紐付いていない場合はエラー

5. GenericPageLoaderで共通ページデータを読み込み
   └─ ヘッダー、フッター等の共通要素

6. LandingPageオブジェクトの生成
   └─ LandingPageEntity をセット

7. メタ情報の設定
   ├─ metaTitle: ランディングページのメタタイトルまたは名前
   ├─ metaDescription: メタ説明
   └─ metaKeywords: キーワード

8. LandingPageLoadedEventのディスパッチ
   └─ 拡張ポイントとしてイベントを発火

9. LandingPageLoadedHookの実行
   └─ App Scriptsによる拡張ポイント

10. Twigテンプレートのレンダリング
    └─ index.html.twig でHTMLを生成してレスポンスを返却
```

### フローチャート

```mermaid
flowchart TD
    A[リクエスト受信] --> B{landingPageIdあり?}
    B -->|No| C[RoutingException発生]
    B -->|Yes| D[LandingPageRoute::load]
    D --> E{ランディングページ存在?}
    E -->|No| F[LandingPageException発生]
    E -->|Yes| G{CMSページあり?}
    G -->|No| H[LandingPageException発生]
    G -->|Yes| I[GenericPageLoader::load]
    I --> J[LandingPage生成]
    J --> K[MetaInformation設定]
    K --> L[LandingPageLoadedEvent発火]
    L --> M[LandingPageLoadedHook実行]
    M --> N[Twigレンダリング]
    N --> O[レスポンス返却]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-001 | ランディングページ必須 | 指定されたIDのランディングページが存在しない場合はエラー | 常時 |
| BR-002 | CMSページ必須 | ランディングページにCMSページが紐付いていない場合はエラー | 常時 |
| BR-003 | メタタイトル優先順位 | metaTitleがない場合はnameを使用 | メタ情報設定時 |
| BR-004 | HTTPキャッシュ対応 | ランディングページはHTTPキャッシュ対象 | 常時 |

### 計算ロジック

特になし

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| ランディングページ取得 | landing_page | SELECT | ランディングページ本体の取得 |
| CMSページ取得 | cms_page | SELECT | 紐付けられたCMSページの取得 |
| 翻訳取得 | landing_page_translation | SELECT | 多言語データの取得 |

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

#### landing_page

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| SELECT | id, active, cms_page_id, name等 | id = {指定されたランディングページID} | active = true でフィルタリング |

#### landing_page_translation

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| SELECT | name, meta_title, meta_description, keywords | landing_page_id + language_id | 現在の言語で取得 |

#### cms_page

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| SELECT | id, sections, blocks, slots等 | id = {CMSページID} | 関連するセクション、ブロック、スロットも取得 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| FRAMEWORK__ROUTING_MISSING_REQUEST_PARAMETER | RoutingException | landingPageIdパラメータ未指定 | パラメータを指定する |
| CONTENT__LANDING_PAGE_NOT_FOUND | LandingPageException | 指定IDのランディングページが存在しない | 正しいIDを指定する |
| CONTENT__PAGE_NOT_FOUND | PageNotFoundException | CMSページが紐付いていない（v6.8.0以前） | CMSページを設定する |

### リトライ仕様

リトライ処理なし（読み取り専用処理のため）

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

読み取り専用のためトランザクション制御なし

## パフォーマンス要件

- HTTPキャッシュ対応（`PlatformRequest::ATTRIBUTE_HTTP_CACHE => true`）
- レスポンス時間：200ms以内推奨

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

- 認証不要（公開領域）
- activeフラグがfalseのランディングページは表示されない
- XSS対策：Twigのエスケープ機能を使用

## 備考

- ランディングページはカテゴリ構造とは独立したURL構造を持つ
- SEO用メタ情報（タイトル、説明、キーワード）を個別設定可能
- CMSページと1対1で紐付く
- App Scriptsでの拡張はLandingPageLoadedHook経由で可能

---

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

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

### 推奨読解順序

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

ランディングページのデータ構造を理解することが重要である。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | LandingPage.php | `src/Storefront/Page/LandingPage/LandingPage.php` | ページオブジェクトの構造（landingPage, metaInformation） |
| 1-2 | LandingPageEntity.php | `src/Core/Content/LandingPage/LandingPageEntity.php` | エンティティの構造（name, cmsPage, metaTitle等） |
| 1-3 | MetaInformation.php | `src/Storefront/Page/MetaInformation.php` | メタ情報の構造 |

**読解のコツ**: LandingPageはPageクラスを継承し、LandingPageEntityを保持する。LandingPageEntityはCmsPageEntityと関連付けられている。

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

処理の起点となるコントローラーを確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | LandingPageController.php | `src/Storefront/Controller/LandingPageController.php` | index()メソッド（36-43行目） |

**主要処理フロー**:
1. **36行目**: ルート定義 - `/landingPage/{landingPageId}`
2. **38行目**: LandingPageLoader::load()を呼び出し
3. **40行目**: LandingPageLoadedHookを実行
4. **42行目**: Twigテンプレートをレンダリング

#### Step 3: ページローダーを理解する

ランディングページデータの読み込み処理の詳細を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | LandingPageLoader.php | `src/Storefront/Page/LandingPage/LandingPageLoader.php` | load()メソッド（33-71行目） |

**主要処理フロー**:
- **35-38行目**: landingPageIdの取得とバリデーション
- **40行目**: LandingPageRoute::load()でランディングページを取得
- **42-49行目**: CMSページの存在チェック（なければ例外）
- **51-52行目**: GenericPageLoaderで共通ページデータを取得
- **54行目**: LandingPageEntityをセット
- **56-64行目**: メタ情報（タイトル、説明、キーワード）を設定
- **66-68行目**: LandingPageLoadedEventをディスパッチ

#### Step 4: Store APIルートを理解する

ランディングページデータの取得処理を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | AbstractLandingPageRoute.php | `src/Core/Content/LandingPage/SalesChannel/AbstractLandingPageRoute.php` | 抽象クラスの定義 |
| 4-2 | LandingPageRoute.php | `src/Core/Content/LandingPage/SalesChannel/LandingPageRoute.php` | 具体的な実装 |

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

```
LandingPageController::index()
    │
    ├─ LandingPageLoader::load()
    │      ├─ AbstractLandingPageRoute::load()
    │      │      └─ LandingPageEntity (+ CmsPageEntity)
    │      ├─ GenericPageLoaderInterface::load()
    │      │      └─ 共通ページデータ（ヘッダー、フッター等）
    │      └─ MetaInformation設定
    │
    ├─ hook(LandingPageLoadedHook)
    │
    └─ renderStorefront() → index.html.twig
```

### データフロー図

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

Request (landingPageId) ────────┐
                                ▼
SalesChannelContext ──────▶ LandingPageController ──────▶ LandingPage
                                │                              │
                                ▼                              ├─ landingPage (LandingPageEntity)
                         LandingPageLoader                     │    └─ cmsPage (CmsPageEntity)
                                │                              └─ metaInformation
                                ├─ LandingPageRoute                   │
                                │      └─ LandingPageEntity           │
                                ├─ GenericPageLoader                  │
                                │      └─ Page (共通データ)           │
                                └─ MetaInformation設定                │
                                                                      ▼
                                                               index.html.twig
                                                                      │
                                                                      ▼
                                                               HTML Response
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| LandingPageController.php | `src/Storefront/Controller/LandingPageController.php` | コントローラー | ランディングページ表示のエントリーポイント |
| LandingPageLoader.php | `src/Storefront/Page/LandingPage/LandingPageLoader.php` | ローダー | ランディングページデータの読み込み |
| LandingPage.php | `src/Storefront/Page/LandingPage/LandingPage.php` | ページ | ランディングページのデータ構造 |
| LandingPageEntity.php | `src/Core/Content/LandingPage/LandingPageEntity.php` | エンティティ | ランディングページのエンティティ |
| LandingPageLoadedEvent.php | `src/Storefront/Page/LandingPage/LandingPageLoadedEvent.php` | イベント | ランディングページ読み込み完了イベント |
| LandingPageLoadedHook.php | `src/Storefront/Page/LandingPage/LandingPageLoadedHook.php` | フック | App Scripts用拡張ポイント |
| AbstractLandingPageRoute.php | `src/Core/Content/LandingPage/SalesChannel/AbstractLandingPageRoute.php` | Store API | ランディングページ取得の抽象クラス |
| MetaInformation.php | `src/Storefront/Page/MetaInformation.php` | データ構造 | SEO用メタ情報 |
