LaravelでCityモデルにPrefectureモデルへの関連が定義されているとします。
<?php
declare(strict_types=1);
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class City extends Model
{
// 略
public function prefecture()
{
return $this->belongsTo('App\Models\Prefecture')->open();
}
}
以下のように、データを取得した後で関連データを参照すると、参照のたびにSQLが発行されます。
N+1問題というやつですね。
$cities = City::get();
foreach($cities as $city) {
var_dump($city->prefecture);
}
対応として、Eager Loadingと呼ばれる事前データ取得処理をおこないます。
Laravelではwithメソッドでモデルを指定します。
$cities = City::with('Prefecture')->get();
foreach($cities as $city) {
var_dump($city->prefecture);
}
// 複数の場合は配列もしくは複数回withメソッドを呼び出します。
$cities = City::with(['Prefecture', 'Towns'])->get();
$cities = City::with('Prefecture')->with('Towns')->get();
さらに、不要なカラムはいらないので、selectメソッドを追加してみます。
$cities = City::select('code')->with('Prefecture')->get();
foreach($cities as $city) {
var_dump($city->prefecture);
}
ぎゃー
NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL (略)
外部キーも指定しないとダメなようです
$cities = City::select(['code', 'prefecture_id'])->with('Prefecture')->get();
foreach($cities as $city) {
var_dump($city->prefecture);
}
ということで、関連テーブルをEagar Lodingで取得する際にselectメソッドを組み合わせる場合は、外部キーもselectに指定する必要があるという覚書でした。