4

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
    ];
});
sepehr
  • 17,110
  • 7
  • 81
  • 119
kk_
  • 302
  • 4
  • 18
  • Possible duplicate of [Laravel - Seeding Relationships](http://stackoverflow.com/questions/35449226/laravel-seeding-relationships) – sepehr Nov 23 '16 at 11:42

3 Answers3

12

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
sepehr
  • 17,110
  • 7
  • 81
  • 119
3

It looks like that, you want to create Companies and Users and also you want to attach users with companies at the same time. If this is what you are trying to achieve then you can do it easily using something like this:

factory(App\Company::class, 10)->create()->each(function($factory) {
    $factory->users()->save(factory(App\User::class)->make());
});

In this case, you have to define the users relationship method in your Company model using the right foreign key.

This will create 10 companies and return a collection so on that collection using each method a single user will be created and attached with that company. Also, check the documentation.

The Alpha
  • 143,660
  • 29
  • 287
  • 307
1

If you're using Laravel 5.2 or above you can use this:

'company_id' => Company::inRandomOrder()->first()->id

jeanj
  • 2,106
  • 13
  • 22