Home > database >  Laravel 9 factory and creating related 1:1 models
Laravel 9 factory and creating related 1:1 models

Time:06-20

I'd like to use Laravel factories to populate some dummy data in my test environment. I have a Locations model and a LocationDetails model, which have a 1:1 relationship and a record needs to be created in the LocationDetails table whenever a new Location is created.

How can I do this in a factory such that there's exactly 1 LocationDetails record for each Location record.

Here's what I have in my DatabaseSeeder class:

    if(env('APP_ENV') === 'local') {
        Client::factory()->count(25)->create();
        Location::factory()->count(30)->create();
    }

My location factory definition:

public function definition()
    {
        return [
            'name' => $this->faker->company,
            'client_id' => Client::all()->random()->id,
            'location_status_id' => LocationStatus::all()->random()->id,
            'address' => $this->faker->streetAddress,
            'city' => $this->faker->city,
            'state' => $this->faker->StateAbbr,
            'zip_code' => $this->faker->numerify('#####'),
            'phone' => $this->faker->numerify('###-###-####'),
            'email' => $this->faker->safeEmail,
            'is_onboarding_completed' => 1,
        ];
    }

It looks like Laravel has an afterCreate() callback for a factory, but I'm just not clear on how to accomplish this.

CodePudding user response:

Does this work

Location::factory()
    ->has(LocationDetails::factory())
    ->count(30)
    ->create();

Or you can have a state defined on the LocationFactory

//LocationFactory
//Assuming location_id is the foreign key on LocationDetails model

public function withLocationDetail()
{
    return $this->afterCreating(function (Location $location) {
        LocationDetails::factory()->create(['location_id' => $location->id]);
    });
}

And then use it like

Location::factory()
    ->withLocationDetail()
    ->count(30)
    ->create();
  • Related