Laravel Factory:手动增加柱子

bna*_*hin 5 php laravel laravel-seeding laravel-5.4

对于以下工厂定义,列order必须是顺序的.已经有一个id自动递增的列.第一行的order应该开始在1每个额外行的order应该是下一个号码(1,2,3等)

$factory->define(App\AliasCommand::class, function (Faker\Generator $faker) {
    return [
        'user_id' => App\User::inRandomOrder()->first()->id,
        'command' => $faker->word,
        'content' => $faker->sentence,
        'order'   => (App\AliasCommand::count()) ?
            App\AliasCommand::orderBy('order', 'desc')->first()->order + 1 : 1
    ];
});
Run Code Online (Sandbox Code Playgroud)

它应该将order列设置为比前一行多1,但是,它会导致所有行都被分配1.

apo*_*fos 15

这可能有用.

$factory->define(App\AliasCommand::class, function (Faker\Generator $faker) {
    static $order = 1;   
    return [
        'user_id' => App\User::inRandomOrder()->first()->id,
        'command' => $faker->word,
        'content' => $faker->sentence,
        'order'   => $order++
    ];
});
Run Code Online (Sandbox Code Playgroud)

它只是在该函数内部保留一个计数器.


Sou*_*ser 7

如果您确定工厂模型生成只会按顺序运行并且您不关心预先存在的数据,@apokryfos 的答案是一个很好的解决方案。

但是,这可能会导致错误的order值,例如,如果您想要生成要插入到测试数据库中的模型,而测试数据库中已经存在一些记录。

使用列值的闭包,我们可以更好地自动化顺序。

$factory->define(App\AliasCommand::class, function (Faker\Generator $faker) {
    return [
        'user_id' => App\User::inRandomOrder()->first()->id,
        'command' => $faker->word,
        'content' => $faker->sentence,
        'order'   => function() {
            $max = App\AliasCommand::max('order'); // returns 0 if no records exist.

            return $max+1;
        }
    ];
});
Run Code Online (Sandbox Code Playgroud)

您在示例中几乎是正确的,问题是您在定义工厂时运行值order执行,而不是上面的代码,后者在生成单个模型时执行。

按照同样的原则,您还应该将user_id代码包含在闭包中,否则所有工厂生成的模型都将具有相同的用户 ID。


Jus*_*ell 5

在 Laravel 9(可能还有一些早期版本?)中,当您创建模型时,有一种非常干净的方法可以实现这一点(来自文档):

$users = User::factory()
    ->count(10)
    ->sequence(fn ($sequence) => ['order' => $sequence->index])
    ->create();
Run Code Online (Sandbox Code Playgroud)

如果您想从1以下内容开始0

$users = User::factory()
    ->count(10)
    ->sequence(fn ($sequence) => ['order' => $sequence->index + 1])
    ->create();
Run Code Online (Sandbox Code Playgroud)