kk_ kk_ - 12 days ago 7
PHP Question

Laravel seeding with factory but extending it

I want a database with two tables Users and Companies and the users table has a foreign key with the company id. So 1 company can have multiple users.

I created the models for this in laravel and also created a factory for each of the tables.

In my seeders I want to create multiple data lines at once and found this solution:

factory(App\Company::class, 10)->create();


This works fine for the company table. But I need to extend this for the users table so it searches for available company Ids.

Any ideas how I can do this?

If I can't search for available Ids, I would also be happy to extend it with the "company_id" field and give it random value from 1-10 (beacause I know that these are the Ids for now).

So basically I want to extend this to use the fields from the factory, but extend it with another field "company_id":

factory(App\Users::class, 10)->create();


Here is the User factory code:

$factory->define(App\User::class, function (Faker\Generator $faker) {
return [
'first_name' => $faker->firstName,
'last_name' => $faker->lastName,
'postcode' => $faker->postcode,
'city' => $faker->city
];
});

Answer

When dealing with such relationships, defining model factories can be a pain. You have a few options though.

Random blind IDs

If you're sure that a common range of IDs is available, you can just generate a random ID to make the relationship work:

$factory->define(App\User::class, function (Faker\Generator $faker) {
    return [
        // ...
        'company_id' => rand(1, 10),
    ];
});

Inline factories

This was the most widely used approach as promoted by Laracast's screencasts:

$factory->define(App\User::class, function (Faker\Generator $faker) {
    return [
        // ...
        'company_id' => factory(App\Company::class)->create()->id,
    ];
});

Or you can go the other way around and create one or more users in the company factory. This way, you only need to run factory() on one of your entities.

Random ID from database

As of Laravel's 5.2 release, you have access to an Eloquent method called inRandomOrder:

$factory->define(App\User::class, function (Faker\Generator $faker) {
    return [
        // ...
        'company_id' => Company::inRandomOrder()->first()->id,
    ];
});

Alternatives for Laravel releases before 5.2:

// Laravel 4.2.7 - 5.1:
User::orderByRaw("RAND()")->get();

// Laravel 4.0 - 4.2.6:
User::orderBy(DB::raw('RAND()'))->get();

// Laravel 3:
User::order_by(DB::raw('RAND()'))->get();

// Source: http://stackoverflow.com/a/13931676/65732
Comments