Laravel Seeding: HasMany with Multiple Levels

When using seeders, the data is often interconnected: we want to seed some data with related records. Is there a "quick" syntax to do it?

If we take a look at Laravel docs, we can find this example:

$user = User::factory()
->has(Post::factory()->count(3))
->create();

This example assumes that the relationship is User -> hasMany -> Posts.

What this example doesn't cover, is that you can chain this deeper, more than one level. So, let's imagine the scenario of this relationship:

Customer -> hasMany -> Order
Order -> hasMany -> Product
Product -> hasMany -> Ingredient

And we need to seed the data for Customers, each with X orders, each order with Y products, and each product with Z ingredients.

If we have the Factory classes for those Models ready, we can write this short chain in the CustomerSeeder or even the DatabaseSeeder file:

public function run()
{
Customer::factory(100)
->has(Order::factory(2))
->has(Product::factory(3))
->has(Ingredient::factory(5))
->create();
}

This will create 100 customers, 2 orders for each customer, 3 products for each order, and 5 ingredients for each product.

Looks like a beautiful one-liner, doesn't it?

You can read more about Laravel factories and seeding in the Laravel docs here.

avatar

This works really well, but I was wondering, is there a way to randomise the number of orders, products and ingredients being created each time, in order to make the seed data a bit more realistic?

I tried to do ->has(Product::factory(rand(1,3))) hoping that it would create between 1 and 3 products for each order but acutally it seems as though it only evaluates the random number once so all of the orders have 1, 2 or 3 products depending on the number it chose.

I know I can achieve this by using a for loop or even each() but then we loose a lot of the beauty of your example.

Like our articles?

Become a Premium Member for $129/year or $29/month
What else you will get:
  • 58 courses (1056 lessons, total 44 h 09 min)
  • 78 long-form tutorials (one new every week)
  • access to project repositories
  • access to private Discord

Recent Premium Tutorials