概要
livewireコンポーネント内のプロパティで使える型に、EloquenCollectionがあります。
通常のSupportCollectionは使えません
EloquentCollectionの便利な所は
内包しているEloquentモデルオブジェクトをlivewireが勝手に配列にしてしまわない所です。
基本的にモデルオブジェクトを内包した配列を生成した場合、モデルオブジェクトが全て配列に変換されてしまいます。
$this->hoge[] = User::find(1);
上記のように記述した場合、レンダリング時にUserモデルオブジェクトがただの配列になります。
EloquentCollectionなら特定のモデルオブジェクトを取り出した際に、モデルが持つ振る舞いを使用する事ができます。
ですが使用する際に注意点があります
永続化されてないモデルオブジェクトをpushするとエラーが発生する
以下のようなlivewireコンポーネントがあるとします
php側
<?php
namespace App\Http\Livewire;
use App\Models\User;
use Illuminate\Database\Eloquent\Collection;
use Livewire\Component;
class Sample1202 extends Component
{
public Collection $users;
public function mount()
{
$this->users = User::all();
}
public function render()
{
return view('livewire.sample1202')
->extends('adminlte::page')
->section('content');
}
public function addUser()
{
$this->users->push(User::make([
'name' => 'John Doe',
'email' => 'john@example.com',
'password' => 'password'
]));
}
}
Blade側
<div>
@foreach($users as $user)
<p>id: {{ $user->id }}</p>
<p>名前:{{ $user->name }}</p>
@endforeach
<button wire:click="addUser">追加</button>
</div>
DB
永続化されてないモデルオブジェクトを追加する
画面
書いたコード通りだと、追加ボタンを押すとJohn Doe
さんが追加されます。
追加ボタンをクリックします。
はい、追加されました。問題なさそうですね。ではもう一度クリックします。
なにやら見慣れないエラーが出ましたね。
Queueing collections with multiple model connections is not supported.
複数のモデル接続を持つコレクションのキューイングはサポートされていません。
対処法
Modelオブジェクト生成時に接続先を教えてあげます。
public function getConnectionName()
{
return $this->connection ?? config('database.default');
}
なぜこんなエラーが起きるのか?
livewire内でEloquentCollectionを使うと、
レンダリングする度にEloquentCollection内のモデルオブジェクトを全て最新の状態にする処理が走ります。
実際に見てみましょう。
まずこの状態から、DBを直接弄って一番上の人の名前を書き換えます
この状態で追加ボタンを押してみます。
はい、livewireコンポーネント内で再取得する処理を記述していないのに更新されました。
これを行おうとした際に発生するエラーという訳です。
実際にどういう処理が行われているのかはまた今度コードの海に潜ってみようと思います。
今回分かったのは大枠の原因と対処法です。