# 機能設計書 38-ビューファインダー

## 概要

本ドキュメントは、Laravel Frameworkにおけるビューファインダー（View Finder）機能の設計書である。ビュー名からファイルシステム上の実際のファイルパスを解決するコンポーネントであり、名前空間ヒントやファイル拡張子の優先順位を管理する。

### 本機能の処理概要

**業務上の目的・背景**：
ビューシステムにおいて、開発者はドット記法のビュー名（例：`users.profile`）で参照するが、実際のファイルは特定のディレクトリ構造に配置されている。ビューファインダーは、このビュー名をファイルパスに変換する役割を担う。また、パッケージのビューを名前空間（`package::view`）で参照できるようにし、テンプレートの構成を柔軟にする。

**機能の利用シーン**：
- コントローラからのビュー参照時のパス解決
- パッケージビューの名前空間参照
- Bladeコンポーネントのテンプレート検索
- ビュー存在確認

**主要な処理内容**：
1. ビュー検索（`find`メソッドによるファイルパス解決）
2. 名前空間ビュー検索（`::` 区切りの名前空間付きビュー解決）
3. パス管理（`addLocation`, `prependLocation`メソッド）
4. 名前空間ヒント管理（`addNamespace`, `prependNamespace`, `replaceNamespace`メソッド）
5. 拡張子管理（`addExtension`メソッド）
6. キャッシュ管理（`flush`メソッド）

**関連システム・外部連携**：
- Filesystem: ファイル存在確認
- ViewFactory: ビュー作成時のパス解決

**権限による制御**：
本機能自体は権限制御を行わない。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | 全Blade画面 | 主処理 | 全てのビュー参照で使用 |

## 機能種別

ファイル検索 / パス解決

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| name | string | Yes | ビュー名（ドット記法、名前空間付き可） | - |
| namespace | string | Yes（名前空間追加時） | 名前空間名 | - |
| hints | string\|array | Yes（名前空間追加時） | 検索パス | - |
| location | string | Yes（パス追加時） | ビューパス | - |

### 入力データソース

- ViewFactoryからの呼び出し
- 設定ファイル（`config/view.php`）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| path | string | ビューファイルの絶対パス |

### 出力先

- 戻り値として呼び出し元に返却

## 処理フロー

### 処理シーケンス

```
1. ビュー検索（find呼び出し）
   └─ ビュー名を受け取る
   └─ キャッシュ確認（既に解決済みか）

2. 名前空間判定
   └─ `::`を含むか確認
   └─ 含む場合は名前空間ビューとして処理

3. 通常ビュー検索
   └─ 登録済みパスを順に検索
   └─ 各パスで可能なファイル名を生成
   └─ ファイル存在確認

4. 名前空間ビュー検索
   └─ 名前空間とビュー名を分離
   └─ 名前空間のヒントパスを取得
   └─ ヒントパス内で検索

5. 結果キャッシュ
   └─ 発見したパスをキャッシュに保存
   └─ 次回以降は直接返却
```

### フローチャート

```mermaid
flowchart TD
    A[find呼び出し] --> B{キャッシュに存在?}
    B -->|Yes| C[キャッシュから返却]
    B -->|No| D{名前空間付き?}
    D -->|Yes| E[findNamespacedView]
    D -->|No| F[findInPaths]
    E --> G[parseNamespaceSegments]
    G --> H{名前空間ヒント存在?}
    H -->|No| I[InvalidArgumentException]
    H -->|Yes| J[findInPaths with hints]
    F --> K[getPossibleViewFiles]
    J --> K
    K --> L{ファイル存在?}
    L -->|Yes| M[キャッシュに保存]
    L -->|No| N[次のパス/拡張子]
    N -->|あり| K
    N -->|なし| O[InvalidArgumentException]
    M --> P[パス返却]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-38-01 | ドット変換 | ビュー名のドットはディレクトリ区切りに変換 | 常時 |
| BR-38-02 | 名前空間区切り | `::` で名前空間とビュー名を区切る | 名前空間使用時 |
| BR-38-03 | パス優先順位 | 先頭に登録されたパスが優先（prepend > add） | 常時 |
| BR-38-04 | 拡張子優先順位 | 先頭に登録された拡張子が優先 | 常時 |
| BR-38-05 | パス長制限 | PHP_MAXPATHLEN - 1 未満のパスのみ有効 | 常時 |

### 計算ロジック

**可能なファイル名生成**:
```php
// 拡張子配列: ['blade.php', 'php', 'css', 'html']
// ビュー名: 'users.profile'
// 結果: ['users/profile.blade.php', 'users/profile.php', 'users/profile.css', 'users/profile.html']
```

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

本機能はデータベース操作を行わない。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | InvalidArgumentException | ビューが見つからない | ビュー名とパスを確認 |
| - | InvalidArgumentException | 無効なビュー名形式 | `::` の使用方法を確認 |
| - | InvalidArgumentException | 未定義の名前空間 | addNamespaceで登録 |

### リトライ仕様

本機能にリトライ機能は含まれない。

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

該当なし

## パフォーマンス要件

- 解決済みビューパスは`$views`配列にキャッシュ
- `flush()`でキャッシュをクリア可能
- パスはrealpath()で正規化し、一貫性を保つ

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

- ビュー名からのパストラバーサル攻撃は、ドット→スラッシュ変換により軽減
- 名前空間は事前登録が必要で、任意のパスは参照不可

## 備考

- `HINT_PATH_DELIMITER`定数（`::`）で名前空間区切りを定義
- パスはコンストラクタでrealpath()により正規化される

---

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

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

### 推奨読解順序

#### Step 1: インターフェースを理解する

まず、ViewFinderの契約を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | ViewFinderInterface.php | `src/Illuminate/View/ViewFinderInterface.php` | ファインダー契約 |

#### Step 2: FileViewFinderクラスを理解する

中核クラスの実装を把握する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | FileViewFinder.php | `src/Illuminate/View/FileViewFinder.php` | ファインダー主実装 |

**主要処理フロー**:
- **15行目**: `$files` - Filesystemインスタンス
- **22行目**: `$paths` - 検索パス配列
- **29行目**: `$views` - 解決済みビューキャッシュ
- **36行目**: `$hints` - 名前空間ヒント
- **43行目**: `$extensions` - 検索拡張子
- **52-60行目**: コンストラクタ - パスの正規化
- **68-79行目**: `find()` - メイン検索メソッド
- **87-92行目**: `findNamespacedView()` - 名前空間ビュー検索
- **102-115行目**: `parseNamespaceSegments()` - 名前空間パース
- **126-139行目**: `findInPaths()` - パス内検索
- **147-150行目**: `getPossibleViewFiles()` - 可能なファイル名生成
- **158-161行目**: `addLocation()` - パス追加
- **169-172行目**: `prependLocation()` - パス先頭追加
- **192-201行目**: `addNamespace()` - 名前空間追加
- **210-219行目**: `prependNamespace()` - 名前空間先頭追加
- **239-246行目**: `addExtension()` - 拡張子追加
- **264-267行目**: `flush()` - キャッシュクリア

**読解のコツ**: `find()`がエントリーポイント。キャッシュ→名前空間判定→検索の流れを追う。

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

```
FileViewFinder::find('users.profile')
    │
    ├─ views['users.profile']確認 ... キャッシュ
    │
    ├─ hasHintInformation() ... '::'の存在確認
    │      └─ false
    │
    └─ findInPaths('users.profile', $paths)
           │
           ├─ getPossibleViewFiles()
           │      └─ ['users/profile.blade.php', 'users/profile.php', ...]
           │
           └─ パスループ
                  └─ files->exists($path)
                         │
                         ├─ 存在 → views['users.profile'] = $path
                         │          └─ $path返却
                         │
                         └─ 不存在 → 次のパス/拡張子

FileViewFinder::find('package::views.index')
    │
    ├─ hasHintInformation() ... '::'の存在確認
    │      └─ true
    │
    └─ findNamespacedView()
           │
           ├─ parseNamespaceSegments()
           │      └─ ['package', 'views.index']
           │
           ├─ hints['package']確認
           │
           └─ findInPaths('views.index', $hints['package'])
```

### データフロー図

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

ビュー名 ──────────────────▶ FileViewFinder::find()
                               │
                         キャッシュ確認
                               │
                         ┌─────┴─────┐
                         │           │
                    キャッシュHit  キャッシュMiss
                         │           │
                    パス返却    名前空間判定
                                     │
                               ┌─────┴─────┐
                               │           │
                          通常ビュー  名前空間ビュー
                               │           │
                          paths検索   hints検索
                               │           │
                               └─────┬─────┘
                                     │
                               ファイル存在確認
                                     │
                               キャッシュ保存
                                     │
                    絶対パス ◀────────┘
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| FileViewFinder.php | `src/Illuminate/View/FileViewFinder.php` | ソース | ビューファインダー主実装 |
| ViewFinderInterface.php | `src/Illuminate/View/ViewFinderInterface.php` | インターフェース | ファインダー契約 |
| ViewServiceProvider.php | `src/Illuminate/View/ViewServiceProvider.php` | ソース | ファインダー登録 |
| Factory.php | `src/Illuminate/View/Factory.php` | ソース | ファインダー利用 |
