greifaxis
greifaxis

Reputation: 5

Laravel 5.8 seeding database with many to many relations

I currently work with Laravel 5.8 and my database has a users table and a roles table that are connected by many to many relation. My intention is to seed whole database in one go using php artisan migrate:fresh --seed however pivot table role_user is always empty, suggesting that something is not right with attach/sync. I intend on implementing more many-to-many relations so I want thoroughly understand seeding these relations using seeders and factories.

How can I seed many-to-many relations and quickly check if these relations are working correctly?

User Model:

    class User extends Authenticatable
    {
        //Default variables generated by Laravel
        public function roles()
        {
           return $this->belongsToMany('App\Role', 'role_user')->withTimestamps();
        }
    }

Role Model:

class Role extends Model
{
    public function users()
    {
        return $this->belongsToMany('App\User', 'role_user')->withTimestamps();
    }
}

Table role_user migration:

  public function up()
    {
        Schema::create('role_user', function (Blueprint $table) {
            $table->bigIncrements('id');
            $table->unsignedBigInteger('role_id');
            $table->unsignedBigInteger('user_id');
            $table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
            $table->foreign('role_id')->references('id')->on('roles')->onDelete('cascade');
            $table->timestamps();
    }

Role Seeder:

public function run()
{
    $role_user = new Role();
    $role_user->role = 'user';
    $role_user->save();

    $role_admin = new Role();
    $role_admin->role = 'admin';
    $role_admin->save();
}

User Seeder:

 public function run()
    {
        $faker = Faker\Factory::create();

        $role_user = Role::where('role','=','user')->first();
        $role_admin  = Role::where('role','=','admin')->first();

        //Generic user account for testing
        $test_user = new User();
        $test_user->username = 'user';
        $test_user->email = '[email protected]';
        $test_user->email_verified_at = now();
        $test_user->password = 'user';
        $test_user->remember_token = Str::random(10);
        $test_user->save();
        $test_user->roles()->attach($role_user);

        //Generic admin account for testing
        $test_admin = new User();
        $test_admin->username = 'admin';
        $test_admin->email = '[email protected]';
        $test_admin->email_verified_at = now();
        $test_admin->password = 'admin';
        $test_admin->remember_token = Str::random(10);
        $test_admin->save();
        $test_admin->roles()->attach($role_admin);
    }

Upvotes: 0

Views: 1829

Answers (1)

Vipertecpro
Vipertecpro

Reputation: 3274

In case you wanted to use via factory,

Create UserFactory.php in factories folder

<?php

use App\User;
use Illuminate\Support\Str;
use Faker\Generator as Faker;

/*
|--------------------------------------------------------------------------
| Model Factories
|--------------------------------------------------------------------------
|
| This directory should contain each of the model factory definitions for
| your application. Factories provide a convenient way to generate new
| model instances for testing / seeding your application's database.
|
*/

$factory->define(App\User::class, function (Faker $faker) {
    return [
        'username'           => $faker->name , 
        'email'              => $faker->unique()->safeEmail , 
        'email_verified_at ' => Str::random(10),
        'remember_token'     => now(),
        'password'           => Hash::make('123456')
    ];
});

Then create RoleUsersFactory.php

<?php

use App\User,App\Role,App\RoleUser;
use Illuminate\Support\Str;
use Faker\Generator as Faker;

/*
|--------------------------------------------------------------------------
| Model Factories
|--------------------------------------------------------------------------
|
| This directory should contain each of the model factory definitions for
| your application. Factories provide a convenient way to generate new
| model instances for testing / seeding your application's database.
|
*/

$factory->define(App\RoleUser::class, function (Faker $faker) {
    return [
        'role_id'   => Role::all()->random()->id,
        'user_id'   => User::all()->random()->id,
    ];
});

Then in your DatabaseSeeder.php add this

factory(App\User::class, 50)->create()->each(function($u) {
    $u->userroles()->save(factory(App\RoleUser::class)->make());
 });

One more thing you need to create RoleUser model and in User model you've setup incorrect relationship role_user doesn't exist in your role table.

I hope this helps

Upvotes: 2

Related Questions