php - How should I use factories in Laravel when I have default values in DB

I have a factory:

$factory->define(\App\MissingData::class, function (Faker $faker) {
    $operations = Operation::all()->pluck('id')->toArray();
    $operationId = $faker->randomElement($operations);
    $operation = Operation::find($operationId);
    $meters = $operation->meters->pluck('id')->toArray();
    $arrStatus = ['Done', 'Undone'];
    return [
        'operation_id' => $operationId,
        'meter_id' => $faker->randomElement($meters),
        'date_ini' => $faker->dateTimeThisYear,
        'date_end' => $faker->dateTimeThisYear,
        'status' => $faker->randomElement($arrStatus),
    ];
});

In my migration, I have:

$table->string('status')->default('Undone');

When I want to insert an array in DB, I always prefer to use factory:

factory(MissingData::class)->create($missingData);

with

return [
                'operation_id' => $measure->operation_id,
                'meter_id' => $measure->meter_id,
                'conso_prod' => $measure->conso_prod,
                'date_ini' => $missingDataIni,
                'date_end' => $missingDataEnd,
            ];

The wanted behaviour is to insert the status: 'Undone' configured in DB, but my factory will generate a fake status, so I will always have to send Undone status to my factory, which is not the point of using a DB default.

How am I supposed to manage this. Using factory to create and insert model is a good practice.

Using default in DB is also very practical, I believe they can be used both at the same time, but I don't see how should I do that.

Any idea ?

Answer

Solution:

Your best bet is probably to default the status to undone then have a seperate state for done and any other status' that you may add.

$factory->define(\App\MissingData::class, function (Faker $faker) {
   $operations = Operation::all()->pluck('id')->toArray();
   $operationId = $faker->randomElement($operations);
   $operation = Operation::find($operationId);
   $meters = $operation->meters->pluck('id')->toArray();

   return [
       'operation_id' => $operationId,
       'meter_id' => $faker->randomElement($meters),
       'date_ini' => $faker->dateTimeThisYear,
       'date_end' => $faker->dateTimeThisYear,
       'status' => 'Undone',
   ];

});

$factory->state(\App\MissingData::class, 'done', fn() => ['status' => 'Done']);

Then when you want the status to be done you would use the state like this.

factory(\App\MissingData)->state('done')->create();

Source