Laravel Factory: Manual Increment of Column

こ雲淡風輕ζ 提交于 2019-12-23 11:56:18

问题


For the following factory definition, the column order needs to be sequential. There is already a column id that is auto-incremented. The first row's order should start at 1 and each additional row's order should be the next number (1,2,3, etc.)

$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
    ];
});

It should be setting the order column to be 1 more than the previous row, however, it results in all rows being assigned 1.


回答1:


Here's something that might work.

$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++
    ];
});

It just keeps a counter internal to that function.




回答2:


To achieve true autoIncrement rather use this approach:

   $__count = App\AliasCommand::count();
   $__lastid = $__count ? App\AliasCommand::orderBy('order', 'desc')->first()->id : 0 ;


   $factory->define(App\AliasCommand::class,
       function(Faker\Generator $faker) use($__lastid){

       return [

         'user_id' => App\User::inRandomOrder()->first()->id,
         'command' => $faker->word,
         'content' => $faker->sentence,
         'order'   => $faker->unique()->numberBetween($min=$__lastid+1, $max=$__lastid+25),

         /*  +25 (for example here) is the number of records you want to insert 
             per run.
             You can set this value in a config file and get it from there
             for both Seeder and Factory ( i.e here ).
         */
      ];

   });



回答3:


The answer by @apokryfos is a good solution if you're sure the factory model generations will only be run in sequential order and you're not concerned with pre-existing data.

However, this can result in incorrect order values if, for example, you want to generate models to be inserted into your test database, where some records already exist.

Using a closure for the column value, we can better automate the sequential 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;
        }
    ];
});

You almost had it right in your example, the problem is that you were running the order value execution at the time of defining the factory rather than the above code, which executes at the time the individual model is generated.

By the same principle, you should also enclose the user_id code in a closure, otherwise all of your factory generated models will have the same user ID.



来源:https://stackoverflow.com/questions/44983693/laravel-factory-manual-increment-of-column

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!