Webアプリ PHP Laravel DB
LaravelでModelを使ったDBの操作の仕組み

クエリビルダーとインスタンス

// クエリビルダー(まだDBに問い合わせていない) Plan::where('user_id', 1) → where('date', $date) // get()で初めてDBに問い合わせてインスタンスが生まれる → get(); // → PlanモデルのインスタンスのCollection
メソッドはインスタンスがないと実行できない。

プロパティとメソッド

プロパティ → テーブルのカラムに対応

$plan → title // plansテーブルのtitleカラム $plan → goal_value // plansテーブルのgoal_valueカラム

メソッド(リレーション) → Plan.phpに自分で定義したもの

$plan → children // Plan.phpにchildren()を定義 $plan → result // Plan.phpにresult()を定義 $plan → unitName // Plan.phpにunitName()を定義
見分け方は $fillable に書いてあるものがプロパティ、function で定義したものがメソッド。

リレーションの種類

$plan → children // HasMany → Collectionで複数返る $plan → result // HasOne → 1件のインスタンスが返る $plan → unitName // BelongsTo → 1件のインスタンスが返る

withとN+1問題

withなし(N+1問題)

$plans = Plan::where(...) → get(); // SQL1回: SELECT * FROM plans foreach ($plans as $plan) { $plan → result; // planの数だけSQL発行 $plan → unitName; // planの数だけSQL発行 } // planが10件 → 合計21回SQL

withあり

$plans = Plan::where(...) → with(['result', 'unitName']) → get(); // SQL1回: SELECT * FROM plans // SQL1回: SELECT * FROM results WHERE plan_id IN (1,2,3...) // SQL1回: SELECT * FROM mst_names WHERE cd IN (...) // 合計3回 foreach ($plans as $plan) { $plan → result; // メモリから返す(SQL発行なし) $plan → unitName; // メモリから返す(SQL発行なし) }

with('children')の仕組み

→ with('children') // 文字列'children'を渡している

Laravelが 'children' という文字列を見て内部で children() メソッドを呼び出してSQLを組み立てる。だからメソッドの定義が必要。

// メソッドがないとエラー Plan::with('children') → get(); // ❌ childrenって何? // メソッドがあるから動く public function children(): HasMany { return $this → hasMany(Plan::class, 'parent_id'); } Plan::with('children') → get(); // ✅

children()は自己結合

public function children(): HasMany { return $this → hasMany(Plan::class, 'parent_id', 'id'); }
-- 同じplansテーブルをparent_idで自己参照 SELECT * FROM plans WHERE parent_id = {親のid}
同じ plans テーブルを parent_id で自己参照している。

JOINとwithの違い

JOIN → フラットな結果、親が子の数だけ重複

parent.id | parent.title | child.title 1 | Laravel学習 | ルーティング理解 1 | Laravel学習 | Blade学習 2 | 運動する | ランニング

with → 階層構造、親は重複しない

$plans[0] title=Laravel学習 children[0] title=ルーティング理解 children[1] title=Blade学習 $plans[1] title=運動する children[0] title=ランニング
.NETで言うとJOINの結果をDataTableで受けて親子に組み立て直す作業をLaravelが自動でやってくれるイメージ。

$plan->unitName? → cd_content

$plan → unitName // BelongsTo → MstNameの1件のインスタンス $plan → unitName → cd_content // そのインスタンスのcd_contentカラム // ? → はnullの場合にエラーにならないようにする $plan → unitName? → cd_content // unitNameがnull(unit_cdが未設定)でもエラーにならずnullを返す
? → を使わないと、unitName が null のときにエラーになる。

hasOneの外部キー規約

public function result(): HasOne { return $this → hasOne(Result::class); // 省略しているが実際は return $this → hasOne(Result::class, 'plan_id', 'id'); // モデル名_id が外部キーの規約 }
SELECT * FROM results WHERE plan_id = {planのid} LIMIT 1
モデル名_id が外部キーの規約。Result → plan_id が自動で使われる。