Laravel=5.6
withとは?
リレーションテーブルのデータを取得するための、Eloquentの記法。N+1問題を防止することができる。
使い方
Account.php
public function posts () {
$this->hasMany('Post');
}
Account::with('posts')->get();
N+1問題とは?
アカウント数+1回のSQLが実行されるためパフォーマンスが悪い
$accounts = Account::get(); // Account::get()でSQL1回実行
foreach ($accounts as $key => $account) {
$accounts[key]->posts = $account->posts; // foreachの回数分SQL実行
}
様々な記法
2つ以上"先"のリレーション
Post.php
public function comments () {
$this->hasMany('Comment');
}
Account::with('posts.comments')->get();
2つ以上のリレーション
Post.php
public function account () {
$this->belongsTo('Account');
}
Post::with(['account', 'comments'])->get();
whereやorder by
アカウントデータをアカウント名昇順でソート
Account::with('posts.comments')->orderBy('name')->get();
コメントデータをコメント日時降順でソート
Account::with(['posts.comments' => function ($query) {
$query->orderByDesc('created_at');
})->get();
投稿データを投稿日時でフィリタリングし、コメントデータも取得
Account::with('posts.comments')->with(['posts' => function($query){
$query->where('created_at', '>', '2023-01-01 00:00:00');
}])->get();
whereHas
リレーション元のデータを、リレーション先のデータでフィルタリング
※withでは、リレーション元のデータをリレーション先のデータでソートやフィルタリングできない
アカウントデータをコメント日時でフィルタリング
Account::whereHas('posts.comments', function ($query) {
$query->where('created_at', '>', '2023-01-01 00:00:00');
})->get();