How to pass arguments to Laravel factories?

40,210

Solution 1

The attributes you pass to the create function will be passed into your model definition callback as the second argument.


In your case you don't even need to access those attributes, since they'll automatically be merged in:

$business = factory(App\Business::class)->create();

factory(App\User::class, 5)->create([
    'business_id' => $business->id,
]);

Adapt this to your needs.

Solution 2

My code for adding polymorphic 'Admin' users was:

// run model factory
factory(App\Admin::class, 3)->create()->each(function ($admin) {

    $admin->user()->save(

        // solved: https://laravel.com/docs/master/database-testing#using-factories (Overriding attributes)
        factory(App\User::class)->make([
              'userable_id' => $admin->id,
              'userable_type' => App\Admin::class
        ])
    );
});

Hope this helps.

Solution 3

Send attribute,

factory(App\User::class)->create(['businessId' => $businessId]);

Retrieve it,

$factory->define(App\User::class, function (Faker $faker, $businessInfo) {
    //$businessInfo['businessId']
});
Share:
40,210
Cristian
Author by

Cristian

Updated on July 09, 2022

Comments

  • Cristian
    Cristian almost 2 years

    I have a users table and a one-to-zero/one relation with a businesses table (users.user_id => businesses.user_id). On my users table I have a discriminator which tells me if the user is of type business and therefore I need to have details on the businesses table as well.

    I want to create my Users with my factory which currently is working and then only create business details where the discriminator points to a business account.

    I have three options in my mind:

    1. Create from users factory and then using '->each()' do some checks on the discriminator and create a new business user using a the factory. However I cannot pass to the business factory the user_id that the user was assigned.
    2. First create the users. Then in my Business seeder, retrieve all Users that match a 'business' discriminator. Then for all of these users run a factory that creates the business details. But again, I would have to link somehow the user_id of the already create user with the business factory user_id.
    3. In my business factory, create a new User and retrieve the id, thus making the link between users.user_id and business.user_id. However I am using a random generator for user.user_type so even if I have the businesses table filled it might be for users that have the discriminator as 'personal'.

    Is there another way? Can I pass arguments from my Seeder to the factory?

  • Cristian
    Cristian over 8 years
    How could I have missed that. I watched the Laracast lesson and I know remember about setting stuff myself. Of course it was in the documentation as well: laravel.com/docs/master/testing#model-factories. Thanks a lot.
  • Harry
    Harry about 7 years
    @Cristian's link looks outdated now, for 5.4 see laravel.com/docs/5.4/database-testing#using-factories & scroll down to 'Persisting Models'
  • Lloric Mayuga Garcia
    Lloric Mayuga Garcia over 6 years
    what about like this? php $student->assignRole('student'); im using spatie/permission
  • shotex
    shotex over 6 years
    what if i don't want to merge them? what if i want to use custom parameters to model factories?
  • Joseph Silber
    Joseph Silber over 6 years
    @shotex - If you want custom parameters, why are you using factories? Just create the model yourself: User::create($attributes)
  • Víctor
    Víctor over 5 years
    @JosephSilber In my case I would want to pass a $user parameter so I can get its type and according to that, get a random value associated with it.
  • PaulH
    PaulH about 5 years
    Great, the manual puts it like this: You may override attributes on the model by passing an array to the create method. laravel.com/docs/5.8/database-testing#persisting-models
  • George
    George over 4 years
    Hello Robin how can i use the variable inside the factory ? not directly override
  • Robin Hood
    Robin Hood over 4 years
    @George Then just use make() without the array of custom values for userable_id and userable_type.
  • George
    George over 4 years
    i want the admin variable to be usable in the User factory, ex if( $admin->name == 'test'} do something
  • Robin Hood
    Robin Hood over 4 years
    Then you'll need to use the Admin class: $admin = new Admin(). 👈 Start there and see where it goes.
  • vikrant
    vikrant over 3 years
    is there a way to access the $admin->id inside user factory?
  • Robin Hood
    Robin Hood over 3 years
    @vikrant I believe $admin->id works within the Admin factory only. For the User factory, I think you have to hard-code the admin ID.
  • mikoop
    mikoop over 2 years
    make doesn't seem to save the record btw
  • mikoop
    mikoop over 2 years
    thanks this is great and help with my seeds