LaravelでEagerロードをしようとした際に、ほんの少しだけ詰まったので備忘録的にまとめました。
はじめに
Laravelには、N+1クエリ問題の解決策として、Eagerロードが用意されています。
このEagerロードを、とあるケースで使おうとした際に、詰まったのでそれについて書いて行きます。
ではまずは、僕がLaravelのEagerロードで詰まったケースについて、まずは提示していきます。
サービス内容
典型的な求人システムの開発
DB設計
usersテーブル |
---|
id |
name |
password |
companiesテーブル |
---|
id |
name |
password |
jobsテーブル |
---|
id |
company_id |
title |
description |
entriesテーブル |
---|
id |
user_id |
job_id |
企業(Company)が求人(Job)を作成し、ユーザー(User)が求人に応募(Entry)
することができる簡単な構成です。
どこで詰まったのか
やりたかったことは、ユーザーのマイページに、応募済みのすべての求人を表示することです。表示される求人には、企業名も表示したいので、企業名をEagerロードする必要がありました。
最初こんな感じで書きました。
public function entriedJobs()
{
$user = Auth::user();
//自分の応募情報をすべて取得する
$entries = App\Entry::where('user_id', $user->id)->get();
$entries->load('job');
//自分の応募情報から求人情報をリレーションですべて取得する
$jobs = [];
foreach ($entries as $entry) {
$jobs[] = $entry->job;
}
return view('user.entried-jobs', [
'user' => $user,
'jobs' => $jobs,
]);
}
ただこれでは、求人(Job)しかEagerロードできていません。企業情報(Company)もEagerロードしたいです。
最初は、以下のようにEagerロードしようとしましたが、ここではリレーションで求人情報を取得しているため、当然エラーがでます。なぜなら、EagerロードはEloquentの動的プロパティを使用した際にしか使えないためです。
$jobs = [];
foreach ($entries as $entry) {
$jobs[] = $entry->job;
}
$jobs->load('company');
あらためてLaravelのドキュメントを確認したところ、ネストしたリレーションをEagerロードする際には、以下のように「ドット」記法が使用できるようです。
public function entriedJobs()
{
$user = Auth::user();
$entries = App\Entry::where('user_id', $user->id)->get();
//ネストした遅延Eagerロード
$entries->load(['job', 'job.company']);
$jobs = [];
foreach ($entries as $entry) {
$jobs[] = $entry->job;
}
return view('user.entried-jobs', [
'user' => $user,
'jobs' => $jobs,
]);
}
参考:Laravel 5.7 Eloquent:リレーション
最後に
よく分からない点や間違っている点がありましたら、コメント欄で教えていただければと思いますm(_ _)m