skip to Main Content

I am trying to build a simple page hierarchy for a website in Laravel and want to create a factory for my Page model. A column in Page is ‘parent_id’ which I want to populate with the id of another random page that has just been created as part of the factory run.

First thing to note is I already have one default page in the db before the factory is run.

So for example, If I use my factory to create 10 pages.

Page::factory()->times(10)->create();

What I WANT to happen is:

  • The first page created will look in the pages table and pick a page at random, then use that id in the parent_id column. There is only one page in the db at this point, so that id is used
  • For the second page, there are now two pages in the database, so one is picked at random and the id is used in the parent_id column
  • For the third page, there are now three pages in the database, so one is picked at random and the id is used in the parent_id column
  • etc. etc.

My (reduced) factory looks like this

public function definition(): array
{
    return [
        'name'        => $this->faker->sentence(5),
        'url'         => $this->faker->url,
        'parent_id'   => Page::all()->random()->id,
    ];
}

But this only gets the id of the first page that is in the DB before the factory is run. All factory built pages have the same parent_id.

How can I update the factory so the parent_id is different for each newly created page?

2

Answers


  1. try parent_id from closure function.

    'parent_id'   => function() {
        return Page::count() > 0 ? Page::all()->random()->id : null;
    },
    
    Login or Signup to reply.
  2. I usually use a factory callback to solve this problem which allows you to perform additional tasks after making or creating a model.

    class PageFactory extends Factory
    {
        protected $model = Page::class;
    
        public function definition(): array
        {
            return [
                'name' => $this->faker->sentence(5),
                'url' => $this->faker->url,
            ];
        }
    
        public function configure()
        {
            return $this->afterCreating(function (Page $page) {
               
                $parentPage = Page::inRandomOrder()->first();
    
    
                if ($parentPage) {
                    $page->parent_id = $parentPage->id;
                    $page->save();
                }
            });
        }
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search