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

Laravel中如何为批量创建的Factory模型设置不同created_at值?

解决Laravel批量创建模型时created_at相同的测试问题

你可以用以下几种方法替代sleep(1),让批量创建的Car模型拥有不同的created_at值,同时保证测试高效准确:

1. 在工厂中使用sequence生成递增时间

批量创建时,通过sequence方法为每个模型的created_at设置递增的时间偏移,无需手动逐个配置:

// 批量创建10个created_at依次递增的Car
$cars = Car::factory()->for($user)
    ->sequence(fn ($sequence) => [
        'created_at' => now()->addSeconds($sequence->index),
        'updated_at' => now()->addSeconds($sequence->index)
    ])
    ->count(10)
    ->create();

$sequence->index会从0开始递增,每个后续模型的时间比前一个晚1秒,完美避免时间重复。

2. 修改Car工厂自动生成递增时间

在CarFactory中加入静态变量控制时间偏移,让每次创建模型时自动累加时间:

class CarFactory extends Factory
{
    protected static $timeOffset = 0;

    public function definition()
    {
        $timestamp = now()->addSeconds(static::$timeOffset++);
        return [
            // 其他字段定义
            'created_at' => $timestamp,
            'updated_at' => $timestamp,
        ];
    }

    // 测试前后重置偏移量,避免测试间干扰
    public static function resetTimeOffset()
    {
        static::$timeOffset = 0;
    }
}

然后在测试类的setUp或tearDown方法中重置偏移:

protected function setUp(): void
{
    parent::setUp();
    CarFactory::resetTimeOffset();
}

这样批量创建时每个Car的时间都会自动递增,无需额外代码。

3. 测试单个时间差时直接指定时间

如果只是测试两个模型的顺序,直接给第二个模型设置比第一个晚的时间,比sleep(1)高效得多:

$user = User::factory()->create(); 
$lessRecentCar = Car::factory()->for($user)->create(); 
$mostRecentCar = Car::factory()->for($user)->create([
    'created_at' => $lessRecentCar->created_at->addSecond(),
    'updated_at' => $lessRecentCar->created_at->addSecond(),
]);

关键补充:确保关联默认按时间倒序

要让$user->cars()默认返回最新创建的Car,需要在User模型的关联方法中加上排序:

public function cars()
{
    return $this->hasMany(Car::class)->orderBy('created_at', 'desc');
}

这样不管模型创建顺序如何,关联查询都会按created_at倒序返回,你的测试断言$hasManyRelation->first()为最新模型才能稳定通过。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 21:40:25