Mojdeh
Mojdeh

Reputation: 33

How to populate a nested category table with Faker in Laravel?

I want to put the subcategory id into quote table but it seems too complicated! This is my try, obviously it ended up with a loop.

Here is the seeder:

public function run()
{
    factory(App\User::class, 50)->create()->each(function ($u) {

        $u->quotes()->save(
            factory(App\Quote::class)->make()
        );

    });
}

And the quote factory:

return [
    'text' => $faker->paragraph,
    'author_id' => factory('App\Author')->create()->id,
    'category_id' => factory('App\Category')->create()->id
];

The category factory:

return [
    'name' => $faker->text,
    'parent_id' => factory('App\Category')->create()->id
];

Upvotes: 3

Views: 7878

Answers (1)

Rwd
Rwd

Reputation: 35180

As long as you're using Laravel >=5.3, I would suggest using states.

For you default category factory make the parent_id = null e.g.

$factory->define(App\Category::class, function (Faker $faker) {
    return [
        'name'      => $faker->text,
        'parent_id' => null
    ];
});

Then you can add a state factory to include the parent category:

$factory->state(App\Category::class, 'child', function ($faker) {
    return [
        'parent_id' => factory('App\Category')->create()->id,
    ];
});

To use the state, you just need to chain on a method called states() with the name of the state e.g.

factory(App\Category::class)->states('child')->make();

If you're using Laravel <=5.2 then I would just suggest keeping the parent_id = null and then just passing the parent_id manually e.g.

$parent = factory(App\Quote::class)->create();
$u->quotes()->save(
    factory(App\Quote::class)->make(['parent_id' => $parent->id])
);

I would also recommend wrapping any factory calls from within a factory in a closure.

'parent_id' => function () {
   return factory('App\Category')->create()->id;
}

This way will only ever create the model when it's needed. If you ever override the value by passing your own id, it won’t actually trigger the function, where as if it wasn’t wrapped in a closure it would call the factory whether or not you passing in an id to override it.

Have a look at the documentation for more information.

Upvotes: 5

Related Questions