[Laravel] Eager Loading 応用: 特定カラムの値によって Eager Loading の動作を変える

特定カラムの値によって Eager Loading の動作を変える

  • ユーザを表す User モデルがある
  • 会社を表す Company モデルがある
  • 学校を表す School モデルがある
  • ユーザの職業を表す $user->job フィールドがある
  • $user->job の値によって Eager Load するリレーションを分岐させたい
    • $user->job === 'office_worker' の場合には $user->company リレーションを読み込む
    • $user->job === 'student' の場合には $user->school リレーションを読み込む

こういう場合には,コレクションクラスを自作します。

app/Collections/UserCollection.php
<?php

declare(strict_types=1);

namespace App\Collections;

use App\User;
use Illuminate\Database\Eloquent\Collection;

class UserCollection extends Collection
{
    /**
     * 所属している組織を Eager Load します。 job フィールドの値によって振り分けられます。
     *
     * @return $this
     */
    public function loadOrganization(): self
    {
        $this->groupBy(
            function (User $user) {
                return $user->job;
            }
        )->each(
            function (self $users) {
                switch ($users->first()->job) {
                    case 'office_worker':
                        return $users->load('company');
                    case 'student':
                        return $users->load('school');
                }
            }
        );
        return $this;
    }
}
app/User.php
class User extends Model
{
    public function newCollection(array $models = []): UserCollection
    {
        return new UserCollection($models);
    }

    public function company(): BelongsTo
    {
        return $this->belongsTo(Company::class);    
    }

    public function school(): BelongsTo
    {
        return $this->belongsTo(School::class);    
    }
}
// ユーザを取得
$users = User::whereIn('job', ['office_worker', 'student'])->get();

// 職業の種類が1種類のときは1クエリで済む
// (2種類の場合は2クエリ必要)
$users->loadOrganization();

ちょっと例があんまり良くないけどたまに使いたくなるテクニック

Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account log in.