LoginSignup
13
7

More than 5 years have passed since last update.

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

Posted at

特定カラムの値によって 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();

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

13
7
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
13
7