Laravel - Seeding Many-to-Many Relationship
Solution 1
You can use attach()
or sync()
method on a many-to-many relationship.
There are multiple ways you can approach this. Here one of them:
// Populate roles
factory(App\Role::class, 20)->create();
// Populate users
factory(App\User::class, 50)->create();
// Get all the roles attaching up to 3 random roles to each user
$roles = App\Role::all();
// Populate the pivot table
App\User::all()->each(function ($user) use ($roles) {
$user->roles()->attach(
$roles->random(rand(1, 3))->pluck('id')->toArray()
);
});
Solution 2
Another way is to use saveMany() function
public function run()
{
factory(App\User::class,3)->create();
$roles = factory(App\Role::class,3)->create();
App\User::All()->each(function ($user) use ($roles){
$user->roles()->saveMany($roles);
});
}
Solution 3
Just for a seeder you can use something like this:
for ($i = 0; $i < 50; $i++) {
$user = factory(App\User::class)->create();
$role = factory(App\Role::class)->create();
DB::table('role_user')->insert([
'user_id' => $user->id,
'role_id' => $role->id
]);
}
But normally you need to define relation like has many through https://laravel.com/docs/5.4/eloquent-relationships#has-many-through
Then you will be able to use:
$user->roles()->save($role);
Solution 4
A much cleaner method can be: after you define the factory for App\User and App\Roles you can call the afterCreating method like this:
$factory->define(App\User::class, function ...);
$factory->define(App\Role::class, function ...);
$factory->afterCreating(App\User::class, function ($row, $faker) {
$row->roles()->attach(rand(1,20));
});
Then in Seeds you first create the roles, then the users
public function run()
{
factory(App\Role::class, 20)->create();
factory(App\User::class, 50)->create();
}
Now you have 50 users each of them with one role attached.
Bilal Khawar
Updated on July 09, 2022Comments
-
Bilal Khawar almost 2 years
I have a
users
table and aroles
table that has a many-to-many relationship. These two tables are connected to a junction table calledrole_user
.This is a model of the tables and its connections.
Below are the Models in my Laravel project:
User
namespace App; use Illuminate\Database\Eloquent\Model; class User extends Model { public function roles() { return $this->belongsToMany('App\Role'); } }
Role
namespace App; use Illuminate\Database\Eloquent\Model; class Role extends Model { public function users() { return $this->belongsToMany('App\User'); } }
Below is the Factory file in the Laravel project:
$factory->define(App\User::class, function (Faker\Generator $faker) { return [ 'name' => $faker->name, 'email' => $faker->unique()->safeEmail, 'password' => $password ?: $password = bcrypt('secret'), ]; }); $factory->define(App\Role::class, function (Faker\Generator $faker) { return [ 'role' => $faker->realText($maxNbChars = 2), 'description' => $faker->realText($maxNbChars = 20), ]; });
Below is the Seed file in the Laravel project:
public function run() { factory(App\User::class, 50)->create()->each(function ($u) { $u->roles()->save(factory(App\Role::class)->make()); }); factory(App\Role::class, 20)->create()->each(function ($u) { $u->users()->save(factory(App\User::class)->make()); }); }
This should populate the
users
table and theroles
table but how do I go about populating therole_user
table? (I don't have a Model file for the junction table.)I'm very new at this so any help would be appreciated. Thanks.
-
Tharindu Sathischandra about 5 yearsCan anyone explain why it chooses random between 1 and 3 instead of random between 1 and 20 (As there are 20 records in Roles, not 3)?
-
Othyn almost 5 yearsCould also say $roles->random(rand(1, $roles->count())) to get from 1 to the max available amount of roles
-
C0chett0 over 4 yearsThis will attach between 1 and 3 random roles to the user. NOT choose a role between id 1 and 3! I guess @peterm wanted to show how to limit (min and max) the number of roles you want to attach.
-
Jacek Dziurdzikowski over 4 yearsThis is going to attach 3 new roles separately to each user, it is not the real many-to-many relation mockup, but many-to-one in fact.
-
miken32 over 2 years"Getting all roles and saving them to variable is not too good idea" why not? There are only 20 values, this is a negligible use of resources. Also this whole method is obsolete with modern versions of Laravel;
factory()
helper isn't even there any more. -
Oybek Odilov over 2 yearsWe don't need all the records stored in the variable to quantify them. Instead, we can immediately grab a count of records. if the person who asked the question uses the @peterm's solution elsewhere he will have performance issues (in this case here is 20 values, but I think, we should give universal answers).