# 機能設計書 6-Eloquent ORM

## 概要

本ドキュメントは、Laravel FrameworkのEloquent ORMについて、その設計思想、処理フロー、および実装詳細を記述したものである。Active Recordパターンに基づくオブジェクト-リレーショナルマッピング機能の設計を定義する。

### 本機能の処理概要

Eloquent ORMは、データベーステーブルをPHPクラス（モデル）として表現し、直感的なオブジェクト操作でデータベースの読み書きを行う機能である。リレーション、スコープ、アクセサ/ミューテタ、イベントなど、豊富な機能を提供する。

**業務上の目的・背景**：データベース操作をオブジェクト指向で行うことで、コードの可読性と保守性を大幅に向上させる。SQL文を直接記述する必要がなく、リレーションの取り扱いも簡潔になる。また、モデルイベントやオブザーバーにより、データ変更時のビジネスロジックを一元管理できる。

**機能の利用シーン**：
- CRUDオペレーション
- リレーションのEager/Lazy Loading
- スコープによるクエリの再利用
- アクセサ/ミューテタによるデータ変換
- イベント/オブザーバーによるフック処理
- ソフトデリート
- タイムスタンプ自動更新

**主要な処理内容**：
1. モデルの属性管理（fill, guarded, fillable）
2. リレーションの定義と解決（hasOne, hasMany, belongsTo等）
3. クエリスコープ（ローカル/グローバル）
4. アクセサ/ミューテタによる属性変換
5. モデルイベントの発火
6. タイムスタンプの自動管理
7. ソフトデリート

**関連システム・外部連携**：
- Query Builder（クエリ構築委譲）
- Event Dispatcher（モデルイベント）
- Collection（結果セット）
- Serialization（JSON/配列変換）

**権限による制御**：モデルレベルでの権限制御はPolicy機能と連携。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 46 | モデルコンポーネント | 補助機能 | 取得されたモデルの表示連携 |

## 機能種別

データアクセス / ORM / モデル管理

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| attributes | array | No | モデル属性 | fillableでフィルタ |
| relations | array | No | ロードするリレーション | - |

### 入力データソース

- アプリケーションコード（モデル操作）
- HTTPリクエスト（フォーム入力）
- データベース（既存データ）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| model | Model | モデルインスタンス |
| collection | Collection | モデルコレクション |

### 出力先

- アプリケーションコード
- JSON/API レスポンス
- データベース（永続化時）

## 処理フロー

### 処理シーケンス

```
1. モデル生成
   └─ new Model($attributes)またはModel::find($id)
2. 属性アクセス
   └─ マジックメソッドでアクセサ/ミューテタ経由
3. リレーション解決
   └─ 動的プロパティで遅延ロードまたはwith()で先読み
4. クエリ構築
   └─ newQuery()でEloquent Builderを取得
5. 永続化
   └─ save()でINSERT/UPDATE実行
6. イベント発火
   └─ creating/created, updating/updated等
```

### フローチャート

```mermaid
flowchart TD
    A[Model::find($id)] --> B[newQuery()]
    B --> C[Eloquent Builder生成]
    C --> D[where('id', $id)]
    D --> E[first()]
    E --> F{レコード存在?}
    F -->|Yes| G[newFromBuilder()]
    F -->|No| H[null返却]
    G --> I[setRawAttributes()]
    I --> J[syncOriginal()]
    J --> K[bootIfNotBooted()]
    K --> L[fireModelEvent('retrieved')]
    L --> M[Model返却]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | 自動タイムスタンプ | created_at/updated_atを自動更新 | timestamps = true |
| BR-02 | Mass Assignment保護 | fillable/guarded属性で一括代入を制御 | fill()呼び出し時 |
| BR-03 | 主キー自動インクリメント | incrementing = true時にINSERT後にIDを取得 | save()時 |
| BR-04 | ソフトデリート | deleted_atにタイムスタンプを設定 | SoftDeletes trait使用時 |
| BR-05 | Lazy Loading防止 | preventLazyLoading()でN+1を検出 | 設定時 |

### 計算ロジック

- テーブル名推測: クラス名をスネークケース複数形に変換（User → users）
- 外部キー推測: リレーション名 + '_id'（user → user_id）

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| find() | モデルテーブル | SELECT | 主キーで1件取得 |
| all() | モデルテーブル | SELECT | 全件取得 |
| create() | モデルテーブル | INSERT | 新規作成 |
| update() | モデルテーブル | UPDATE | 更新 |
| delete() | モデルテーブル | DELETE/UPDATE | 削除（ソフトデリート時はUPDATE） |
| save() | モデルテーブル | INSERT/UPDATE | 永続化（exists判定で分岐） |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | MassAssignmentException | 保護された属性への代入 | fillable/guardedを確認 |
| - | ModelNotFoundException | findOrFail()でレコードなし | 404レスポンス返却 |
| - | LazyLoadingViolationException | 遅延ロード禁止時 | with()でEager Loading |

### リトライ仕様

モデル操作にリトライ機能はない。

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

モデル操作はConnectionのトランザクションに従う。saveQuietly()でイベント抑制可能。

## パフォーマンス要件

- N+1問題回避のためEager Loadingを推奨
- 大量データはcursor()またはchunk()を使用
- 不要な属性はselect()で限定

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

- Mass Assignment攻撃対策（fillable/guarded）
- hidden属性でシリアライズ時に機密情報を除外
- casts属性で型安全性を確保

## 備考

- グローバルスコープでテナント分離などを実装可能
- アトリビュートを使用したBoot/Initializeの自動呼び出し
- カスタムEloquent Builderの指定が可能

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | Model.php | `src/Illuminate/Database/Eloquent/Model.php` | モデルの基底クラス |

**読解のコツ**: Modelクラスは複数のトレイトで構成される。まず使用しているトレイトの一覧を確認すること（HasAttributes, HasEvents, HasRelationships等）。

#### Step 2: コアプロパティを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | Model.php | `src/Illuminate/Database/Eloquent/Model.php` | コアプロパティ定義 |

**主要プロパティ**:
- **59-66行目**: connection, table, primaryKey, keyType
- **87-88行目**: incrementing
- **94-101行目**: with, withCount（Eager Loading）
- **115-122行目**: perPage, exists, wasRecentlyCreated
- **283-290行目**: CREATED_AT, UPDATED_AT定数

#### Step 3: トレイトを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | HasAttributes.php | `src/Illuminate/Database/Eloquent/Concerns/HasAttributes.php` | 属性管理 |
| 3-2 | HasEvents.php | `src/Illuminate/Database/Eloquent/Concerns/HasEvents.php` | イベント管理 |
| 3-3 | HasRelationships.php | `src/Illuminate/Database/Eloquent/Concerns/HasRelationships.php` | リレーション定義 |
| 3-4 | GuardsAttributes.php | `src/Illuminate/Database/Eloquent/Concerns/GuardsAttributes.php` | Mass Assignment保護 |

#### Step 4: Eloquent Builderを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | Builder.php | `src/Illuminate/Database/Eloquent/Builder.php` | Eloquent固有のクエリビルダ |

**読解ポイント**:
- Query Builderを内包し、モデル固有の処理を追加
- with()でEager Loading
- scopes()でスコープ適用

#### Step 5: リレーションを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | HasOne.php | `src/Illuminate/Database/Eloquent/Relations/HasOne.php` | 1対1リレーション |
| 5-2 | HasMany.php | `src/Illuminate/Database/Eloquent/Relations/HasMany.php` | 1対多リレーション |
| 5-3 | BelongsTo.php | `src/Illuminate/Database/Eloquent/Relations/BelongsTo.php` | 逆リレーション |
| 5-4 | BelongsToMany.php | `src/Illuminate/Database/Eloquent/Relations/BelongsToMany.php` | 多対多リレーション |

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

```
User::find($id)
    │
    └─ Model::__callStatic('find', [$id])
           │
           └─ (new static)->find($id)
                  │
                  └─ Model::newQuery()
                         │
                         └─ newEloquentBuilder(newBaseQueryBuilder())
                                │
                                ├─ setModel($this)
                                │
                                └─ withGlobalScopes()
                                       │
                                       └─ Eloquent\Builder::find($id)
                                              │
                                              ├─ where('id', $id)
                                              │
                                              └─ first()
                                                     │
                                                     ├─ Query\Builder::get()
                                                     │
                                                     └─ hydrate($results)
                                                            │
                                                            ├─ newFromBuilder($attributes)
                                                            │      ├─ newInstance()
                                                            │      ├─ setRawAttributes()
                                                            │      └─ syncOriginal()
                                                            │
                                                            └─ fireModelEvent('retrieved')
```

### データフロー図

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

Model::find($id) ──────▶ Eloquent Builder ──────────────▶ Model Instance
                              │
                              ▼
                        Query Builder
                              │
                              ▼
                        Grammar (SQL生成)
                              │
                              ▼
                        Connection (クエリ実行) ─────────▶ DBMS
                              │
                              ▼
                        hydrate() (モデル化)
                              │
                              ├── setRawAttributes()
                              ├── syncOriginal()
                              └── fireModelEvent() ─────────▶ Event Dispatcher
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| Model.php | `src/Illuminate/Database/Eloquent/Model.php` | ソース | モデル基底クラス |
| Builder.php | `src/Illuminate/Database/Eloquent/Builder.php` | ソース | Eloquentクエリビルダ |
| Collection.php | `src/Illuminate/Database/Eloquent/Collection.php` | ソース | モデルコレクション |
| HasAttributes.php | `src/Illuminate/Database/Eloquent/Concerns/HasAttributes.php` | ソース | 属性管理トレイト |
| HasEvents.php | `src/Illuminate/Database/Eloquent/Concerns/HasEvents.php` | ソース | イベント管理トレイト |
| HasRelationships.php | `src/Illuminate/Database/Eloquent/Concerns/HasRelationships.php` | ソース | リレーション管理トレイト |
| HasTimestamps.php | `src/Illuminate/Database/Eloquent/Concerns/HasTimestamps.php` | ソース | タイムスタンプ管理 |
| GuardsAttributes.php | `src/Illuminate/Database/Eloquent/Concerns/GuardsAttributes.php` | ソース | Mass Assignment保護 |
| HidesAttributes.php | `src/Illuminate/Database/Eloquent/Concerns/HidesAttributes.php` | ソース | シリアライズ制御 |
| SoftDeletes.php | `src/Illuminate/Database/Eloquent/SoftDeletes.php` | ソース | ソフトデリート |
| Relation.php | `src/Illuminate/Database/Eloquent/Relations/Relation.php` | ソース | リレーション基底クラス |
