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

Laravel 8自关联Contest模型数据填充报错解决方法

解决Laravel填充自关联模型时array_rand()空数组报错的问题

这个错误的原因很直观:当你执行填充器时,第一次运行的瞬间Contest表是空的,你调用\App\Models\Contest::all()->pluck('id')->toArray()得到的是空数组,而array_rand()函数无法处理空数组,所以抛出了ErrorException array_rand(): Array is empty。

你的原代码核心问题是:试图一次性创建10条数据,但在创建开始前就去获取Contest的id列表——这时候数据库里还没有任何数据,自然是空数组。

下面给你两种实用的解决方案:

方案一:先创建根竞赛,再生成子竞赛

先创建一批无父级的根竞赛,再基于这些根竞赛的id来分配子竞赛的父级,确保始终有可用的id数组:

public function run()
{
    // 先创建5个无父级的根竞赛
    $rootContests = \App\Models\Contest::factory(5)->create(['contest_id' => null]);

    // 再创建10个子竞赛,从根竞赛中随机选取父级id
    \App\Models\Contest::factory(10)->create([
        // 使用闭包,每个模型创建时动态获取随机父级id
        'contest_id' => fn () => $rootContests->random()->id
    ]);
}

方案二:混合创建根节点与子节点

如果你希望既有根节点(无父级)又有子节点,还可以随机控制是否分配父级,同时确保第一次创建时有初始数据存在:

public function run()
{
    // 先创建第一个根竞赛,确保数据库有初始数据
    \App\Models\Contest::factory()->create(['contest_id' => null]);

    // 循环创建14条数据,随机决定是否设置父级
    for ($i = 0; $i < 14; $i++) {
        \App\Models\Contest::factory()->create([
            'contest_id' => rand(0, 1) 
                ? \App\Models\Contest::all()->random()->id 
                : null
        ]);
    }
}

关键注意点

  • 避免在批量创建时直接用array_rand(\App\Models\Contest::all()->pluck('id')->toArray()),因为这个值是在所有模型开始创建前就计算好的,此时数据库还是空的。
  • 使用Laravel工厂的闭包(fn () => ...)可以让每个模型在创建时动态计算字段值,这样前面创建的模型已经存入数据库,后续就能获取到有效的id了。

内容的提问来源于stack exchange,提问作者Owen Kelvin

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.11 08:07:37