relationLoadedは「このリレーション、すでにメモリに読み込み済み?」をチェックするメソッドです。
超シンプルなイメージ
Eloquentモデルには $relations という「荷物置き場」があります。
Eager Loadingで事前にリレーションを読み込むと、そこにデータが置かれます。
$user = User::with('posts')->first(); // postsを事前に読み込み → $user->relations['posts']にデータが入る
$user->relationLoaded('posts'); // true が返る(「postsはもう読み込み済みだよ」)
読み込んでない状態:
$user = User::first(); // postsはまだ読み込んでない
$user->relationLoaded('posts'); // false が返る(「postsはまだ読み込んでないよ」)
$user->posts; // ←ここで初めてLazy Loading実行!
どういう時に使うの?(実例)
1. 「読み込み済みならスキップ、未読ならload()」パターン
public function show(User $user)
{
// postsがまだ読み込んでなかったら、今読み込む
if (!$user->relationLoaded('posts')) {
$user->load('posts');
}
return view('user.show', compact('user'));
}
2. 複数モデルを処理する時に便利
$users = User::all();
foreach ($users as $user) {
if (!$user->relationLoaded('profile')) {
$user->load('profile');
}
echo $user->profile->name;
}
→ 全部に一律load()すると無駄なクエリが出るのを防げます。
中身はどうなってるの?(Laravelの内部)
Laravelのコード(簡略化):
// Model.php内部
protected $relations = []; // リレーションの「荷物置き場」
public function relationLoaded($key)
{
return array_key_exists($key, $this->relations); // 「この荷物、ある?」
}
流れ:
-
with('posts')→$relations['posts'] = データ← 事前に入ってる -
$user->postsにアクセス →relationLoaded('posts')チェック → trueなら即返す -
falseならLazy Loading実行 → DBクエリ →
$relations['posts']にセット