syntax error
syntax error

Reputation: 15

Seeding a table with a primary key that is also a foreign key in Laravel

I have a Users table that acts as an abstract table for Engineers and Architects tables.

Users [id (PK), first_name, last_name, role] where 'role' is either 'Engineer' or 'Architect' Engineers [id (PK/FK), experience, skill_set] where foreign 'id' references 'id' on 'Users'
Architects [id (PK/FK), certification, level] where foreign 'id' references 'id' on 'Users'

(The table attributes are arbitrary. I just wanted to get the idea across. Basically there's two tables that share common attributes. The common attributes have been moved in to it's own table).

After I seed the Users table I need to seed the Engineers table with unique Id's matching Users table (since it's a PK and an FK) where Users.role == 'Engineer'.
The same must be done for Architects.

My current solution is to create Users, do a query to get all users where 'role' is 'Engineer' and in a foreach statement create Engineers for each user.

class DatabaseSeeder extends Seeder
{
    public function run()
    {
        $faker = Faker\Factory::create();

        $users = factory(App\User::class, 10)->create(); // Create Users
        $engineers = App\User::all()->where('role', 'engineer');

        foreach($engineers as $engineer){
            App\Engineer::create([
                'id' => $engineer->id,
                ...
            ]);
       }
    }
}

How can move App\Engineer to it's own Seeder?

My thought process was to create an array of users where 'role' == 'engineer'. Then pop off a user and use that user's User->id when creating an Engineer.

class EngineersTableSeederextends Seeder
{
    public function run()
    {
        $engineers = App\User::all()->where('role', 'engineer');
        $engineer = array_pop( $engineers );

        factory(App\Engineer::class, 10)->create()->each(function($e) {
            //$p-> ; ???
        });
    }
}

I also tried this inside EngineerFactory;

use Faker\Generator as Faker;

$factory->define(App\Engineer::class, function (Faker $faker) {

    return [
        'id' => $faker->unique()->randomElement(App\User::all()->where('roles', 'engineer')->pluck('id')->toArray()),
        ...
    ];
});

However, because of the unique() modifier I get a Maximum retries of 10000 reached without finding a unique value error. It works if I have about a 100 Users but only create 10 Engineers.

I'm not sure if this is the right approach.

Upvotes: 0

Views: 1679

Answers (1)

Lloople
Lloople

Reputation: 1844

id should never be a foreign key, if your engineers needs to be related to a user, create a user_id field on engineers table. Then your seeders will be:

$users = factory(App\User::class, 10)->create(); // Create Users
$usersEngineers = App\User::all()->where('role', 'engineer');

foreach($usersEngineers as $userEngineer){
    App\Engineer::create([
        'user_id' => $userEngineer->id,
        ...
    ]);
}

Or you can define your engineer factory like this:

use Faker\Generator as Faker;

$factory->define(App\Engineer::class, function (Faker $faker) {

    $userEngineer = factory(App\User::class)->create();
    // some logic to assign engineer role to $userEngineer
    return [
        'user_id' => $userEngineer
        ...
    ];
});

Upvotes: 1

Related Questions