Nevermore
Nevermore

Reputation: 1743

Laravel Seeding using Factory for one to one relation

I want to create a test data using laravel seed. I can seed for one table. Here is :

ModelFactory.php:

/** @var \Illuminate\Database\Eloquent\Factory $factory */
$factory->define(App\User::class, function (Faker\Generator $faker) {
    static $password;

    return [
        'email' => $faker->unique()->safeEmail,
        'password' => $password ?: $password = bcrypt('secret'),
        'remember_token' => str_random(10),
        'type' => '0'
    ];
});

UsersTableSeeder.php :

<?php

use Illuminate\Database\Seeder;

class UsersTableSeeder extends Seeder
{
    /**
     * Run the database seeds.
     *
     * @return void
     */
    public function run() {
        factory(App\User::class, 50)->create()->each(function ($u) {
            $u->posts()->save(factory(App\Post::class)->make());
        });
    }
}

I have two tables which are users and user_information. They have one-to-one relation. I want to seed user_information with users. But i have no idea, how i can do...

My models relation functions :

User.php

public function userInformation() {
        return $this->hasOne('App\UserInformation', 'user_id', 'id');
    }

UserInformation.php

public function users() {
        return $this->belongsTo('App\User', 'user_id', 'id');
    }

Laravel version is 5.3

I followed these docs :

https://laravel.com/docs/5.3/seeding

https://laravel.com/docs/5.3/database-testing#writing-factories

Upvotes: 2

Views: 9040

Answers (3)

rajoyish
rajoyish

Reputation: 11

This works in Laravel 9. Amend your DatabaseSeeder.php such as:

public function run()
    {
        User::factory(10)->create()->each(function ($user) {
            $phone = Phone::factory()->make();
            $user->phone()->save($phone); // phone() is hasOne ralationship in User.php        
        });
    }

You don't need to define user_id column in PhoneFactory.php. The Laravel automatically saves corresponding user_id in the database.

Upvotes: 1

Sambasten
Sambasten

Reputation: 259

For one-to-one relationships, its good practice to make the relationship methods singular

User.php

public function userInformation() 
{
     return $this->hasOne('App\UserInformation', 'user_id', 'id');
}

UserInformation.php

public function user() 
{
        return $this->belongsTo('App\User', 'user_id', 'id');
}

Above solution for Laravel 8, userInformation factory will have :

'user_id' => User::factory()->create()->id,

if you need to create userInformation table only when there's a corresponding user, the above solution will seed new user_ids into the userinformation table and you may end up with more userinformation rows than users. To fix this, you need to seed only UserInformation Factory seeder in DatabaseSeeder run method and not UserFactory. it will automatically seed the users table.

Alternatively, if you have the users table already defined and wants to seed userInformation table for your number of users.

For Laravel 8, its is shown below:

public function definition()
{
    $users = User::all();
    return [
        'name' => $this->faker->company,
        'user_id' => $this->faker->unique()->numberBetween(1, $users->count())
    ];

}

Since its a one to one relationship. You can generate the list of users and use unique and numberBetween functions to fill unique user_ids.

Upvotes: 4

Ari
Ari

Reputation: 885

Answering because this came up in a Google search and might help others:

AFAIK the model hasn't got anything to do with seeding, that's used for query building and constraints.

What can do is create a user, every time you call on your factory that requires the user_id.

Credit to prodigy10 for this answer.

$factory->define(User_Information::class, function ($faker) use ($factory) {
    return [
    'name' => $faker->company(),
    'user_id' => factory(User::class)->create()->id
    ];
});

Upvotes: 5

Related Questions