You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.13 03:35:19