To achieve the desired behavior in your factory, you can use the afterMaking and afterCreating state callbacks to check if a version_id has been passed and handle it accordingly. Here's how you can modify your PriceListFactory:
class PriceListFactory extends Factory
{
/**
* The name of the factory's corresponding model.
*
* @var string
*/
protected $model = PriceList::class;
/**
* Define the model's default state.
*
* @return array
*/
public function definition(): array
{
return [
// Do not set 'version_id' here, handle it in the afterMaking callback
'name' => $this->faker->text(255),
'created_at' => now(),
'updated_at' => now(),
];
}
/**
* Configure the factory to handle version_id appropriately.
*
* @return $this
*/
public function configure()
{
return $this->afterMaking(function (PriceList $priceList) {
// If version_id is not set or is null, handle it accordingly
if (!isset($priceList->version_id) || $priceList->version_id === null) {
$priceList->version_id = $priceList->version_id ?? (Version::factory()->create())->id;
}
// If version_id is set, it will be used as is
});
}
}
With this setup, you can now create PriceList instances with the following scenarios:
- If you don't pass a
version_id, it will create a newVersionand use itsid. - If you pass a
version_idas an integer, it will use that integer. - If you pass a
version_idasnull, it will setversion_idtonull.
Here's how you can use the factory:
// Creates a new Version and uses its id
$result = PriceList::factory()->create();
$this->assertEquals(1, $result->version_id);
// Uses the existing Version with id 2
$result = PriceList::factory()->create(['version_id' => 2]);
$this->assertEquals(2, $result->version_id);
// Sets version_id to null
$result = PriceList::factory()->create(['version_id' => null]);
$this->assertNull($result->version_id);
This approach ensures that the version_id is handled correctly based on the input provided when creating a new PriceList instance.