Livewire挂载时生成集合,刷新时变为数组的问题求助
问题:Livewire刷新后Eloquent对象变为数组,导致"Attempt to read property 'game' on array"错误
我有一个Livewire控制器,在mount()方法中生成按开始日期分组的Game集合并赋值给公共属性$games,Blade组件循环遍历日期渲染数据,点击wire:click按钮触发refreshThis()方法刷新数据后,$game变成数组而非Eloquent对象,子组件报错;但手动刷新页面显示正常。
代码示例
Livewire控制器mount方法
public $games; protected $rules = []; ... public function mount() { $now = Carbon::now(); $games = Game::where('start', '>', $now)->orderBy('start', 'ASC')->get(); $games = $games->groupBy(function($item) { return $item->start->format("Y-m-d H:i:s"); })->collect(); $this->games = $games; }
父Blade组件循环
@foreach($games as $date => $thegames) <div> {{ \Carbon\Carbon::createFromFormat("Y-m-d H:i:s", $date)->format("l jS \of F Y - g:i A") }} </div> <div> <x-individual.game :allgames="$thegames" :user="Auth::user()"></x-individual.game> </div> @endforeach
子Blade组件
@foreach($allgames as $game) <div> <div> <h3> {{ $game->game->name }} </h3> </div> </div> @endforeach
refreshThis方法
public function refreshThis() { $now = Carbon::now(); $games = Game::where('start', '>', $now)->get(); $games = $games->groupBy(function($item) { return $item->start->format("Y-m-d"); })->collect(); $this->games = $games; $this->emit('refreshComponent'); }
原因分析
- Livewire在组件更新时会对公共属性做序列化/反序列化处理,分组后的集合经过反序列化后会变成数组,而非保留Eloquent集合对象的结构。
groupBy()本身返回的是Collection,但Livewire的序列化机制处理嵌套集合时,会将内部的Eloquent对象转为数组,导致子组件遍历的$game变成数组,无法调用Eloquent对象的关联属性(比如$game->game->name)。
解决方案
方案1:修正refreshThis方法的集合处理
groupBy()已经返回Collection,不需要额外调用->collect(),直接赋值即可,确保结构正确:
public function refreshThis() { $now = Carbon::now(); $games = Game::where('start', '>', $now)->get(); // 去掉多余的->collect(),groupBy返回的就是Collection $this->games = $games->groupBy(function($item) { return $item->start->format("Y-m-d"); }); $this->emit('refreshComponent'); }
方案2:添加属性类型转换
在Livewire控制器中指定$games的类型为集合,让Livewire自动处理序列化/反序列化:
public $games; protected $casts = [ 'games' => 'collection', ];
这样即使经过序列化,$games也会被自动转为Collection,内部的Eloquent对象结构得以保留。
方案3:临时子组件兼容处理(不推荐)
如果无法修改控制器,可在子组件中手动将数组转为Eloquent对象:
@foreach($allgames as $game) @php if(is_array($game)) { $game = Game::find($game['id']); } @endphp <div> <div> <h3>{{ $game->game->name }}</h3> </div> </div> @endforeach
内容的提问来源于stack exchange,提问作者Giles Bennett
相关产品推荐
相关产品推荐

