# 機能設計書 65-robots.txt表示

## 概要

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

### 本機能の処理概要

本機能は、検索エンジンのクローラー制御用のrobots.txtを動的に生成し、`/robots.txt`エンドポイントで提供する機能である。

**業務上の目的・背景**：SEO（検索エンジン最適化）において、robots.txtは検索エンジンのクローラーに対してクロール可否を指示する重要なファイルである。適切に設定することで、プライベートページや管理画面のインデックスを防ぎ、重要なページのクロール効率を向上させる。また、サイトマップの場所を明示的に通知することもできる。

**機能の利用シーン**：
- 検索エンジンのクローラー（Googlebot等）がrobots.txtを取得する際
- 管理者がrobots.txtの設定内容を確認する際
- SEO診断ツールからrobots.txtを参照する際

**主要な処理内容**：
1. リクエストを受信（`/robots.txt`）
2. 現在のホスト名に対応する販売チャネルドメインを取得
3. システム設定からrobots.txtルールを取得
4. ルールをパースしてUser-agentブロックとパスディレクティブを構成
5. サイトマップURLを生成
6. robots.txt形式でレスポンスを返却

**関連システム・外部連携**：SalesChannelDomainリポジトリ、SystemConfigService

**権限による制御**：特別な権限制御なし（公開領域）

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 62 | SEO設定 | 補助機能 | SEO URL・メタ情報の設定 |

## 機能種別

データ連携 / ファイル出力

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| request | Request | Yes | HTTPリクエストオブジェクト | - |
| context | Context | Yes | フレームワークコンテキスト | - |

### 入力データソース

- HTTPリクエスト: HTTP_HOSTヘッダーからホスト名を取得
- データベース: sales_channel_domain（販売チャネルドメイン情報）
- システム設定: `core.basicInformation.robotsRules`

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| page | RobotsPage | robots.txtページオブジェクト |
| page.globalUserAgentBlocks | array<RobotsUserAgentBlock> | グローバルUser-agentブロック |
| page.domainRules | DomainRuleCollection | ドメイン別ルールコレクション |
| page.sitemaps | array<string> | サイトマップURLリスト |

### 出力先

- テキスト形式のHTTPレスポンス
- Content-Type: `text/plain; charset=utf-8`
- テンプレート: `robots.txt.twig`

## 処理フロー

### 処理シーケンス

```
1. RobotsController::robotsTxt() がリクエストを受信
   └─ ルート: /robots.txt

2. RobotsPageLoader::load() を呼び出し

3. ホスト名の取得
   └─ HTTP_HOSTヘッダーから取得

4. 販売チャネルドメインの検索
   └─ ホスト名を含むドメインをDBから取得

5. robotsルールの収集
   ├─ 各ドメインのシステム設定からルールを取得
   ├─ RobotsDirectiveParserでパース
   ├─ User-agentブロックの構築
   └─ ドメイン別パスディレクティブの構築

6. サイトマップURLの生成
   └─ 各ドメインの /sitemap.xml URL

7. RobotsPageオブジェクトの生成

8. RobotsPageLoadedEventのディスパッチ

9. robots.txt.twig でテキストを生成
   └─ Content-Type: text/plain を設定して返却
```

### フローチャート

```mermaid
flowchart TD
    A[リクエスト受信] --> B[RobotsPageLoader::load]
    B --> C{ホスト名あり?}
    C -->|No| D[空のRobotsPage]
    C -->|Yes| E[ドメイン検索]
    E --> F[販売チャネルドメイン取得]
    F --> G[ルール収集ループ]
    G --> H[SystemConfig取得]
    H --> I[RobotsDirectiveParser]
    I --> J[User-agentブロック構築]
    J --> K[パスディレクティブ構築]
    K --> L{次のドメイン?}
    L -->|Yes| G
    L -->|No| M[サイトマップURL生成]
    M --> N[RobotsPage生成]
    D --> N
    N --> O[RobotsPageLoadedEvent]
    O --> P[robots.txt.twig]
    P --> Q[Content-Type: text/plain]
    Q --> R[レスポンス返却]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-001 | ホスト名ベース | 現在のホスト名に対応するドメインのルールのみ適用 | 常時 |
| BR-002 | HTTPS優先 | 同じホスト名でHTTP/HTTPSがある場合はHTTPSを優先 | ドメイン選択時 |
| BR-003 | サイトマップ自動追加 | 各ドメインのサイトマップURLを自動的に追加 | 常時 |
| BR-004 | マルチドメイン対応 | 複数ドメインがある場合、パス別にディレクティブを出力 | 複数ドメイン時 |
| BR-005 | User-agentブロック重複排除 | 同一内容のUser-agentブロックはハッシュで重複排除 | 常時 |

### 計算ロジック

特になし

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| ドメイン検索 | sales_channel_domain | SELECT | ホスト名に対応するドメインを検索 |

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

#### sales_channel_domain

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| SELECT | id, url, sales_channel_id等 | url LIKE '%{hostname}%' AND type = STOREFRONT | ストアフロントタイプのみ |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | なし | ホスト名が空の場合 | 空のRobotsPageを返却（エラーにしない） |
| - | なし | 対応するドメインがない場合 | 空のRobotsPageを返却（エラーにしない） |

### リトライ仕様

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

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

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

## パフォーマンス要件

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

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

- 認証不要（公開領域）
- APIルートスコープとStorefrontルートスコープの両方でアクセス可能
- 管理画面URLなどをDisallowに設定してクロール防止を推奨

## 備考

- robots.txtは標準的な形式に準拠
- システム設定からカスタムルールを設定可能
- RobotsDirectiveParserによりルールをパースして構造化
- 複数販売チャネルドメインに対応

---

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

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

### 推奨読解順序

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

robots.txtのデータ構造を理解することが重要である。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | RobotsPage.php | `src/Storefront/Page/Robots/RobotsPage.php` | ページの構造（domainRules, sitemaps, globalUserAgentBlocks） |
| 1-2 | RobotsUserAgentBlock.php | `src/Storefront/Page/Robots/Struct/RobotsUserAgentBlock.php` | User-agentブロックの構造 |
| 1-3 | DomainRuleCollection.php | `src/Storefront/Page/Robots/Struct/DomainRuleCollection.php` | ドメイン別ルールコレクション |
| 1-4 | RobotsDirective.php | `src/Storefront/Page/Robots/Struct/RobotsDirective.php` | 個別ディレクティブの構造 |

**読解のコツ**: RobotsPageはグローバルなUser-agentブロックと、ドメイン別のルールコレクションを持つ。User-agentブロックにはAllow/Disallowなどのディレクティブが含まれる。

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

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

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

**主要処理フロー**:
1. **34-42行目**: ルート定義 - `/robots.txt`、HTTPキャッシュ対応
2. **43行目**: RobotsPageLoader::load()を呼び出し
3. **47-48行目**: robots.txt.twigをレンダリング、Content-Type設定

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

robots.txtデータの読み込み処理を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | RobotsPageLoader.php | `src/Storefront/Page/Robots/RobotsPageLoader.php` | load()メソッド全体 |

**主要処理フロー**:
- **38-40行目**: RobotsPageオブジェクトを生成
- **42-43行目**: ホスト名の取得
- **44-56行目**: ホスト名がある場合の処理
  - **45行目**: getDomains()でドメインを取得
  - **47行目**: collectRules()でルールを収集
  - **49-51行目**: RobotsPageにデータをセット
- **58-60行目**: RobotsPageLoadedEventをディスパッチ

#### Step 4: ルールパーサーを理解する

ルール解析処理を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | RobotsDirectiveParser.php | `src/Storefront/Page/Robots/Parser/RobotsDirectiveParser.php` | parse()メソッド |

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

```
RobotsController::robotsTxt()
    │
    └─ RobotsPageLoader::load()
           ├─ getDomains()
           │      └─ SalesChannelDomainRepository::search()
           ├─ collectRules()
           │      ├─ selectDomainsByHostname()
           │      ├─ SystemConfigService::getString('robotsRules')
           │      └─ RobotsDirectiveParser::parse()
           │             └─ RobotsUserAgentBlock, RobotsDirective
           ├─ getSitemaps()
           │      └─ domain.url + '/sitemap.xml'
           └─ RobotsPageLoadedEvent
                  │
                  ▼
           render() → robots.txt.twig
```

### データフロー図

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

Request (/robots.txt) ──────────┐
                                ▼
HTTP_HOST ──────────────▶ RobotsController ──────▶ Text Response
                                │                      │
                                ▼                      │
                         RobotsPageLoader              │
                                │                      │
                                ├─ SalesChannelDomain  │
                                │      └─ url, salesChannelId
                                │                      │
                                ├─ SystemConfig        │
                                │      └─ robotsRules  │
                                │                      │
                                ├─ RobotsDirectiveParser
                                │      └─ UserAgentBlocks
                                │                      ▼
                                └─ RobotsPage ──▶ robots.txt.twig
                                       │               │
                                       ├─ globalUserAgentBlocks
                                       ├─ domainRules  │
                                       └─ sitemaps     ▼
                                                Content-Type: text/plain
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| RobotsController.php | `src/Storefront/Controller/RobotsController.php` | コントローラー | robots.txt表示のエントリーポイント |
| RobotsPageLoader.php | `src/Storefront/Page/Robots/RobotsPageLoader.php` | ローダー | robots.txtデータの読み込み |
| RobotsPage.php | `src/Storefront/Page/Robots/RobotsPage.php` | ページ | robots.txtのデータ構造 |
| RobotsPageLoadedEvent.php | `src/Storefront/Page/Robots/RobotsPageLoadedEvent.php` | イベント | robots.txt読み込み完了イベント |
| RobotsDirectiveParser.php | `src/Storefront/Page/Robots/Parser/RobotsDirectiveParser.php` | パーサー | robotsルールのパース |
| ParsedRobots.php | `src/Storefront/Page/Robots/Parser/ParsedRobots.php` | データ構造 | パース結果の構造 |
| RobotsUserAgentBlock.php | `src/Storefront/Page/Robots/Struct/RobotsUserAgentBlock.php` | データ構造 | User-agentブロック |
| RobotsDirective.php | `src/Storefront/Page/Robots/Struct/RobotsDirective.php` | データ構造 | 個別ディレクティブ |
| DomainRuleCollection.php | `src/Storefront/Page/Robots/Struct/DomainRuleCollection.php` | データ構造 | ドメイン別ルールコレクション |
