makeabledk / laravel-factory-enhanced

Supercharge your Laravel tests & seeds with nested relations.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Generate random number of relationships

deligoez opened this issue · comments

Hi! Thanks for this great factory package. I have a simple question.

How can we generate random number of related models_?

For example:

factory(Show::class)
    ->with(random_int(2, 10) ,'trackers')
    ->times(random_int(10, 20))
    ->create();

This code will create exactly same number of Tracker's for every Show.
How can I generate random number of Tracker's for every Show

Hey @deligoez

In this case you'd want to put the count in a closure:

factory(Show::class)
    ->with('trackers', fn ($trackers) => $trackers->times(random_int(2, 10)))
    ->times(random_int(10, 20))
    ->create();

The closure should get evaluated each time and thereby produce different results.

Let me know if this solves your problem :-)

Hej @rasmuscnielsen

Unfortunately that didn't work too.

There is always same amount of Trackers through this sample code.

That is a seeder

factory(Show::class)
    ->with('trackers', function($trackers) { $trackers->times(random_int(2, 5)); })
    ->times(random_int(10, 30))
    ->create();

That is the relationship

public function trackers(): HasMany
{
    return $this->hasMany(Tracker::class);
}

And that is the TrackerFactory

$factory->define(Tracker::class, function (Faker $faker, array $attributes) {
    return [
        'show_id' => factory(Show::class)->lazy(),
        'service' => $faker->randomElement(TrackerType::getValues()),
        'code'    => $faker->numerify('##########'),
    ];
});

Hey @deligoez

I just had another look at this with fresh eyes, and unfortunately this is currently not possible due to the inner workings of the package. Only attributes will be re-evaluated for each model.

I realized the readme wrongly indicated this was this case, and have now updated it so it doesn't mislead anyone.

What I would do in your case is something alike the following:

factory(Show::class)
    ->times(random_int(10, 30))
    ->create()
    ->each(function ($show) {
        $show->trackers()->saveMany(
            factory(Tracker::class)->times(random_int(2, 5))->make()
        );
    });

Hope this solves your problem.