Mena
Mena

Reputation: 2029

Unable to seed db table with relationship in Laravel

In a laravel 5.8 application, I want to seed the users & products table. There is a relationship between the users & products like this

User.php model (users can have one or more products)

public function products()
{
    return $this->hasMany(Product::class, 'user_id');
}

Product.php model (a product can belong to one or more users)

public function users()
{
    return $this->belongsToMany(User::class);
}

I am trying to use the UsersTableSeeder below to seed both the users table & products table at the same time

public function run()
{
    factory(App\User::class, 3)->create()->each(function ($user) {
        $user->products()->save(factory(App\Product::class, 3)->make());
    });
}

and the 'DatabaseSeeder`looks like this

public function run()
{
    $this->call(UsersTableSeeder::class);
}

When I run the command php artisan db:seed, only the users table is seeded and I get this error

Symfony\Component\Debug\Exception\FatalThrowableError : Argument 1 passed to Illuminate\Database\Eloquent\Relations\HasOneOrMany::save() must be an instance of Illuminate\Database\Eloquent\Model, instance of Illuminate\Database\Eloquent\Collection given, called in C:\Users\Elomena\Projects\Clients\Pramopro\database\seeds\UsersTableSeeder.php on line 15

This is line 15 $user->products()->save(factory(App\Product::class, 3)->make());

I really don't understand why I am getting this error as I have followed the exact thing from the https://laravel.com/docs/5.8/seeding#using-model-factories

Please how should seeding with relationships be done?

Upvotes: 1

Views: 1043

Answers (2)

rpm192
rpm192

Reputation: 2454

The error message suggests that you're using a collection instead of a model.

The error is caused by this function, it returns a collection and not a model, because it's a hasMany relationship.

public function products()
{
    return $this->hasMany(Product::class, 'user_id');
}

So, you should change your seeder to saveMany instead of save.

public function run()
{
    factory(App\User::class, 3)->create()->each(function ($user) {
        $user->products()->saveMany(factory(App\Product::class, 3)->create());
    });                   // ^ saveMany instead of save
}

Upvotes: 1

Mesuti
Mesuti

Reputation: 908

This can be solve your problem:

public function run()
{
    factory(App\User::class, 3)->create()->each(function ($user) {
        $user->products()->saveMany(factory(App\Product::class, 3)->create());
    });
}

Upvotes: 6

Related Questions