【Laravel8】CollectionクラスでModelクラスのようなsetAppends関数を使う方法

Laravel

スポンサーリンク

ModelクラスにあるsetAppends関数をCollectionクラスでも使いたいなーと思ったのでその方法を紹介します。

前提

例えば、以下のようにして、UserモデルのCollectionクラスに対して、setAppendsを使用すると

$userCollection = User:all();
$userCollection->setAppends(['example']);

以下のようなエラーになる。

Method Illuminate\\Database\\Eloquent\\Collection::setAppends does not exist.

これはCollectionクラスにはsetAppendsという関数は存在していないためです。
ModelクラスにはsetAppends関数が存在していますが、Collectionクラスには存在していません。

そういう時はCollectionクラスにMacroを作成して、あたかもCollectionクラスにModelクラスのsetAppends関数と同様のものが存在しているかのようにしましょう。

作り方

1.Macroを記載するサービスプロバイダを作成します。

php artisan make:provider MacroServiceProvider

2.作成したMacroServiceProvider.phpのboot関数内にCollectionクラスにMacroを追加するように記載

<?php

namespace App\Providers;

use Illuminate\Database\Eloquent\Collection;
use Illuminate\Support\ServiceProvider;

class MacroServiceProvider extends ServiceProvider
{
    /**
     * Bootstrap services.
     *
     * @return void
     */
    public function boot()
    {
        // CollectionクラスにsetAppendsというマクロを登録
        Collection::macro('setAppends', function ($accessorList) {
            return $this->map(function ($model) use ($accessorList) {
                // Collectionから一つずつModelを取り出して、ModelクラスのsetAppendsを使用
                return $model->setAppends($accessorList);
            });
        });
    }
}

3.config/app.phpにプロバイダ(MacroServiceProvider)を登録

// 省略
'providers' => [
    // 省略
    App\Providers\MacroServiceProvider::class,
],

完成

これで、以下のようにCollectionクラスに登録したマクロのsetAppendsを呼び出せるようになり、ModelクラスのsetAppends関数と同じ動きになる。

$userCollection = User:all();
$userCollection->setAppends(['example']);

Laravel

Posted by ton