LoginSignup
2
1

More than 5 years have passed since last update.

LaravelのRelationshipsを取得する際の注意点(selectで外部キーも指定しないとnull)

Posted at

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に指定する必要があるという覚書でした。

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1