Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Better way of Seeding a Pivot Table

I have the following tables users , roles and the pivot table role_user with the following table structure

users

  • id
  • username
  • password

roles

  • id
  • role

role_user

  • id
  • role_id
  • user_id

        <?php
             class PivotTableSeeder extends Seeder {
                 public function run()
                 {
                  // Seeds the roles table
                    DB::table('roles')->delete();
    
                    DB::table('role_user')->insert(array(
                    array('user_id' => 1, 'role_id' => 1),
                    array('user_id' => 2, 'role_id' => 2),
                    array('user_id' => 3, 'role_id' => 1),
                    array('user_id' => 3, 'role_id' => 3),
                    array('user_id' => 3, 'role_id' => 5)
                ));
                }
            }
    

The pivot table is seeded using DB select

Is there a better way to seed the tables, including the pivot table?

I was thinking maybe when I seed my users table, it will also seed the role_user table instead of manually inserting the data into the pivot table.

Example:

roles

  • id = 1
  • role = encoder
  • id = 2
  • role = tech
  • id = 3
  • role = sales

users

  • id = 1
  • username = user
  • password = pass
  • id = 2
  • username = user2
  • password = pass2

role_user

  • id = 1
  • user_id = 1
  • role_id = 1
  • id = 2
  • user_id = 1
  • role_id = 2
  • id = 3
  • user_id = 2
  • role_id = 3

Edit

I am seeding my users table by using this Eloquent. Is there anyway that while seeding the User, the role_user will also get updated?

User::create(array(
    'id' => '1',
    'username' => 'user',
    'password' => 'pass'
));
User::create(array(
    'id' => '2',
    'username' => 'user2',
    'password' => 'pass2'
));
like image 587
lozadaOmr Avatar asked May 02 '14 16:05

lozadaOmr


3 Answers

You may try this (Assuming that you have already seeded roles):

$user = User::create(['id' => '1', 'username' => 'user', 'password' => 'pass']);
$user->roles()->sync([1,2]); // array of role ids

$user = User::create(['id' => '2', 'username' => 'user2', 'password' => 'pass2']);
$user->roles()->sync([3,4]); // array of role ids

I've used [] instead of array(), if your PHP is prior to ver-5.4 then you should use array().

like image 55
The Alpha Avatar answered Nov 12 '22 23:11

The Alpha


For testing purposes I use pretty simple and fast method like below.

Imagine we have users and categories with pivot table (this comes from JeffreyWay's generators btw):

<?php

// Composer: "fzaninotto/faker": "v1.3.0"
use Faker\Factory as Faker;

class UsersTableSeeder extends Seeder {

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

        foreach(range(1, 100) as $index)
        {
            User::create([
                'username'   => $username = $faker->userName,
                'email'      => $faker->email,
                'password'   => Hash::make($username),
                'account_id' => $index
            ]);
        }
    }

}

// all other seeders look the same, so I paste just the code that matters:
// Categories
    foreach(range(1, 30) as $index)
    {
        Category::create([
            'name' => $faker->word
        ]);
    }

// pivot table
    foreach(range(1, 50) as $index)
    {
        DB::table('category_user')->insert([
            'category_id' => rand(1,30),
            'user_id' => $faker->unique()->randomNumber(1, 100)
        ]);
    }
like image 28
Jarek Tkaczyk Avatar answered Nov 12 '22 23:11

Jarek Tkaczyk


For n:m Relationships, where I need to attach random entries, I use this simple but efficient Seeder code, that only uses real ids:

    $faker = Faker\Factory::create();

    $limit = 100;

    for ($i = 0; $i < $limit; $i++) {
        $newrow = *Yourmodel*::create ([
            'email' => $faker->word . rand(0, 9999) . '@test.com' ,
          ...
        ]);

        $ids = $faker->randomElements( \App\YourOtherModel::select('id')->get()->toArray(), rand(1,*3*) );
        foreach($ids as $id) {
            $newrow->*your_relationship*()->attach( $id );
   }
like image 2
Ben Avatar answered Nov 12 '22 23:11

Ben