1

I'm trying to seed my Laravel 5.6 application through faker factory, I went through the link and little bit confused, As I have some basic static data, like for example I've a company model:

class Company extends Model {

    use SoftDeletes, HasDataSearchTable, HasSlug;

    protected $fillable = [
        'name', 'code_link', 'slug', 'establishment', 'parent_id', 'website', 'updates', 'user_id', 'tracked', 'verified', 'active', 'premium', 'status'
    ];

    /**
     * The attributes that should be hidden for arrays.
     *
     * @var array
     */
    protected $hidden = [
        'created_at','updated_at','deleted_at'
    ];

    public function roles()
    {
        return $this->belongsToMany('Noetic\Plugins\Conxn\Models\Variables\Company\Role', 'company_role_relation', 'company_id', 'role_id')->withTimestamps();
    }
}

And a relational role model:

class Role extends Model
{
    use SoftDeletes  , HasDataSearchTable;

    protected $table='company_role';

    protected $fillable = [
        'name', 'parent_id'
    ];

    /**
     * The attributes that should be hidden for arrays.
     *
     * @var array
     */
    protected $hidden = [
        'created_at','updated_at','deleted_at'
    ];

}

and respective database, I'm following the laravel convention, Now I want to seed the data:

I've particular set of roles which I'm seed in manually,

class CompanyRoleSeed extends Seeder
{
    /**
     * Run the database seeds.
     *
     * @return void
     */
    public function run()
    {
        DB::table('company_role')->insert([
            ['name' => 'Contractor', 'parent_id' => null],
            ['name' => 'Consultant', 'parent_id' => null],
            ['name' => 'Manufacturer', 'parent_id' => null],
            ['name' => 'Miscellaneous', 'parent_id' => null],
            ['name' => 'Owner', 'parent_id' => null],
            ['name' => 'Supplier', 'parent_id' => null],
        ]);

    }
}

For company I want to create factory so I did:

$factory->define(Company::class, function (Faker $faker) {


    return [
        'name' => $faker->company,
        'code_link' => rand(5, 10),
        'slug' => str_slug($faker->company),
        'about' => $faker->paragraphs(),
        'establishment' => $faker->randomElement('2015', '2016', '2017', '2018'),
        'parent_id' => $faker->randomElement(null, '1', '2', '3'),
        'website' => $faker->url,
        'user_id' => $faker->randomElement('1', '2', '3', '4', '5'),
        'updates' => $faker->paragraphs(),
        'tracked' => $faker->boolean,
        'verified' => $faker->boolean,
        'active' => $faker->boolean,
        'premium' => $faker->boolean,
        'status' => $faker->randomElement('saved', 'draft')
    ];
});

And in company seed I'm having:

class CompanySeed extends Seeder
{
    /**
     * Run the database seeds.
     *
     * @return void
     */
    public function run()
    {
        factory(Company::class, 10)->create()->each(function ($company) {
            $company->roles()->save(); // Don't now how to execute here
        });
    }
}

Help me at place $company->roles()->save(); What should I do over here.

Any guidance or improvisation welcome.

Nitish Kumar
  • 6,054
  • 21
  • 82
  • 148

2 Answers2

3

You can query which roles you want to assign to the companies and related them to the created records like this:

class CompanySeed extends Seeder
{
    public function run()
    {
        $contractorRole = Role::whereName('Contractor')->firstOrFail();
        $ownerRole = Role::whereName('Owner')->firstOrFail();

        factory(Company::class, 10)->create()->each(function ($company) use ($contractorRole, $ownerRole) {
            $company->roles()->attach([
                $contractorRole->id,
                $ownerRole->id
            ]);
        });
    }
}

You can check the doc for relating records https://laravel.com/docs/5.6/eloquent-relationships#inserting-and-updating-related-models

thefallen
  • 9,496
  • 2
  • 34
  • 49
  • Hey thanks for the reply, I have one doubt, I'm defining a Many to many relationship in my company model with role, so this `saveMany()` will work? – Nitish Kumar May 31 '18 at 07:48
  • @NitishKumar, my mistake, I've updated the method with `attach()` for many to many. – thefallen May 31 '18 at 07:52
  • Can I use random collection method to use any of the values, as this seems to me that every time it will have `$contractorRole` and `$ownerRole`. – Nitish Kumar May 31 '18 at 07:54
  • Use the factory for that, look my answer I've done it like that :D – Pol Lluis May 31 '18 at 07:55
  • Or pull a random $contractorRole and $ownerRole inside the each function – Pol Lluis May 31 '18 at 07:56
  • @NitishKumar, this is just an example, as I see that you are inserting predefined roles in the database, so you can query them and assign random ones to each company. – thefallen May 31 '18 at 07:56
1

before answering your question you should know that Laravel's documentation explains how to do this.

But in order to save a related Model you first need to create a fake one, or in your case relate a role you have already created. In order to do this you could first create a Role factory using something like this:

$factory->define(App\Role::class, function (Faker $faker) {
    $randomRoleAlreadyCreated = \App\Role::all()->random();
    return [
        'name' => $randomRoleAlreadyCreated->name, 
        'parent_id' => $randomRoleAlreadyCreated->parent_id
    ];
});

As you can see on Role factory I created I pull a random Role since you stated that you already created them manually, so if you choose one randomly then your companys will be related to one of your roles randomly!

Once you have: Roles created in DB, factory of roles, you could relate random roles to a company using the factory to save a random instance.

factory(Company::class, 10)->create()->each(function ($company) {
        $company->roles()->save(factory(App\Role::class)->make()); // Don't now how to do here
    });

Update If you want to save multiple roles for each company you could do this:

factory(Company::class, 10)->create()->each(function ($company) {
        // Instead of 4 you could also create a random number 
        // using $numberOfRolesToAttach = rand($min,$max)
        for($i = 1; $i <= 4; $i++) :
            $company->roles()->save(factory(App\Role::class)->make());
        endfor;

    });
Pol Lluis
  • 1,152
  • 7
  • 17
  • Thanks for the update, but I'm not having any random element in roles I have fixed data of `contractors, consultants, owners ` etc.. – Nitish Kumar May 31 '18 at 07:56
  • I know, thats why it will be chosen randomly from consultants, owners, contractors, etc.. Because inside the factory you are pulling ONE OF THEM randomly -> App\Role::all()->random()->name – Pol Lluis May 31 '18 at 08:00
  • So you mean `App\Role::all()->random()->name` will not create any new fake data, or will not create any repetitive data in `Role` model. – Nitish Kumar May 31 '18 at 08:06
  • It will pull **one of your manually created roles**, because you are selecting the model, and random() returns a instance created on the db chosen randomly – Pol Lluis May 31 '18 at 08:08
  • Updated the factory so maybe it looks more clear now – Pol Lluis May 31 '18 at 08:09