6
4

More than 1 year has passed since last update.

Laravel 8.40にEloquentリリーションwithOnly関数到着

Last updated at Posted at 2021-05-14

概念

モデルを取得するときに、常にいくつかのリレーションをロードしたい場合は、モデルの$withプロパティで定義出来ますが、このPRでデフォルトのEagerロードをオーバーライドして、$withプロパティ内のすべてのアイテムを取得せず、withOnlyで定義されているリレーションのみ取得することができるようになりました。

セットアップ

ジュースの管理システムを例にして、ジュース、ジュースのメーカー(作っている会社)と種類(トマト、アップルなどなど)のモデルでそれぞれの適切な情報を管理する。その上この例のサービスの仕組みではジュースのモデルのデータを取得するとき、ほぼ全ての場合においてメーカーの情報も必要となります。(たとえばメーカーの名前を表示することなど)。そのためジュースのモデルの$withで定義することになって、デフォルトでloadすることにします。

このようなジュースのモデルは下記のようになります。


<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

/**
 *ジュースモデル
 * 
*/
class Juice extends Model
{
    /**
     * 常にデフォルトとしていつも取得するリレーション定義
     *
     * @var array
     */
    protected $with = ['maker'];

    /**
     * このJUICEを作っている会社
     */
    public function maker()
    {
        return $this->belongsTo(Maker::class);
    }

    /**
     * JUICEの種類
     */
    public function type()
    {
        return $this->belongsTo(Type::class);
    }
}

デフォルトでmakerがていぎされていますので、取得する時メーカーの情報が自動的にジュースモデルと一緒に取得されます

$juice = App\Models\Juice::first();

// メーカーのリレーションも取得される

App\Models\Juice {
     id: 1,
     name: 'めっちゃおいしいジュース',
     maker_id: 1,
     type_id: 1,
    ...
     maker: App\Models\Maker {
       id: 1,
       name: 'いい会社なまえ',
       ....
     },
   }

withOnlyの使い方

typeを引数としてwithOnlyの関数にわたして、メーカー(デフォルトでロードされるリレーション)の情報が取得されなくなります。

$juice = App\Models\Juice::withOnly('type')->first();

// メーカーのリレーション取得しない
// 種類のリレーションがロードされる

App\Models\Juice {
     id: 1,
     name: 'めっちゃおいしいジュース',
     maker_id: 1,
     type_id: 1,
    ...
     type: App\Models\Type {
       id: 1,
       type_name: 'オレンジ',
       ....
     },
   }

複数のリレーションを取得したいときにはwithOnlyにリレーションの名前の配列を渡すことができます(デフォルトのEagerロードで定義されているリレーションでも可能)。空の配列の場合、すべてのリレーションが取得しないようになります。


$juice = App\Models\Juice::withOnly(['type', 'maker'])->first();

// メーカーと種類のリレーションどっちも取得

App\Models\Juice {
     id: 1,
     name: 'めっちゃおいしいジュース',
     maker_id: 1,
     type_id: 1,
    ...
     type: App\Models\Type {
       id: 1,
       type_name: 'オレンジ',
       ....
     },
    maker: App\Models\Maker {
       id: 1,
       name: 'いい会社なまえ',
       ....
     },
   }

まとめ

$withプロパティ内のリレーションを除外でき、withOnlyの関数の引数にわたされているリレーションのみ取得することが簡単にできます。

参照

https://github.com/laravel/framework/pull/37144
https://laravel.com/docs/8.x/eloquent-relationships#eager-loading-by-default

6
4
1

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
6
4