Laravel: Two Ways to Seed Data with Relationships

While seeding data, it's common to have one class for each database table. But what if there are relationships? I will show you two ways you can deal with it. Imagine we have this simple database structure - database contacts and contact_companies (taken from our Contact Management module in QuickAdminPanel): contact management laravel How to seed data in both tables? Of course, we will use Faker library, but still - there are a few ways to implement it. First, let's define our factories. database/factories/ContactCompanyFactory.php:
$factory->define(App\ContactCompany::class, function (Faker\Generator $faker) {
    return [
        'name' => $faker->name,
        'address' => $faker->address,
        'website' => 'https://' . $faker->word . '.com',
        'email' => $faker->email,
    ];
});
And database/factories/ContactFactory.php:
$factory->define(App\Contact::class, function (Faker\Generator $faker) {
    return [
        'first_name' => $faker->firstName(),
        'last_name' => $faker->lastName,
        'phone1' => $faker->phoneNumber,
        'phone2' => $faker->phoneNumber,
        'email' => $faker->email,
        'skype' => $faker->word,
        'address' => $faker->address,
    ];
});
Now, as you can see, there's no contacts.company_id defined. Here's where we have a few options:

Version 1. Create contacts inside of company seed

Let's create a company seeder:
php artisan make:seeder CompanySeed
And then fill the file database/seeds/CompanySeed.php with this:
public function run()
{
    factory(App\ContactCompany::class, 10)->create()->each(function ($company) {
        $company->contacts()->save(factory(App\Contact::class)->make());
    });
}
Basically, we're creating 10 companies, and for each of them we're creating one contact, using Eloquent relationship in app/ContactCompany.php:
public function contacts()
{
    return $this->hasMany(Contact::class, 'company_id');
}

Version 2. Create company along with the contact

The other way around would be to use seed for Contacts.
php artisan make:seeder ContactSeed
And then add only this line in database/seeds/ContactSeed.php:
public function run()
{
    factory(App\Contact::class, 10)->create();
}
You're probably wondering where the relationship would come from? We can create a "parent" entry directly in the factory! Like this: database/factories/ContactFactory.php:
$factory->define(App\Contact::class, function (Faker\Generator $faker) {
    return [
        'company_id' => factory('App\ContactCompany')->create()->id,
        'first_name' => $faker->firstName(),
        'last_name' => $faker->lastName,
        'phone1' => $faker->phoneNumber,
        'phone2' => $faker->phoneNumber,
        'email' => $faker->email,
        'skype' => $faker->word,
        'address' => $faker->address,
    ];
});
See the first field? We're using parent factory and creating a company "on-the-fly". That's it, isn't it simple? In official Laravel documentation you can find more information about seeding and using factories with Faker.
avatar

In Laravel 9 we need to chnage few things to work with Factory Relationships. Let's continue with Version 01 example.

In Model app/Models/ContactCompany.php

public function contacts()
{
    return $this->hasMany(Contact::class, 'company_id');
}

Let's start.

hasContacts() refers to hasMany relation define in Model. In model we use smallcase method exactly like contacts() but in factory/seeder we use firstlater capital with has keyword.

ContactCompany::factory()
    ->count(6)
    ->hasContact(2) // create two records/contact of each company
    ->create();


OR

ContactCompany::factory()
    ->count(6)
    ->has(Contact::factory()->count(3), 'contacts')
    ->create();


OR


ContactCompany::factory()
->hasContact(2, function (array $attributes, ContactCompany $contactCompany) {
    return ['contact_type' => $contactCompany->type];
})	
👍 1

Like our articles?

Become a Premium Member for $129/year or $29/month
What else you will get:
  • 58 courses (1054 lessons, total 46 h 42 min)
  • 78 long-form tutorials (one new every week)
  • access to project repositories
  • access to private Discord

Recent Premium Tutorials