Reputation: 1562
I'm using the following code to create 20 posts, each of which has 3 comments.
Post::factory()
->times(20)
->has(Comment::factory()->times(3))
->create()
Instead I'd like to create 20 posts, each of which has a random number of comments (e.g. post 1 has 2 comments, post 2 has 4 comments, etc.)
This did not work, each post had the same (random) number of comments.
Post::factory()
->times(20)
->has(Comment::factory()->times(rand(1, 5)))
->create()
How can I achieve this?
Upvotes: 6
Views: 2170
Reputation: 42695
I would use a factory method to do this. Add a method to your Post
factory like this:
<?php
namespace Database\Factories\App;
use App\Comment;
use App\Post;
use Illuminate\Database\Eloquent\Factories\Factory;
class PostFactory extends Factory
{
public function definition(): array
{
return [
// ...
];
}
public function addComments(int $count = null): self
{
$count = $count ?? rand(1, 5);
return $this->afterCreating(
fn (Post $post) => Comment::factory()->count($count)->for($post)->create()
);
}
}
Then in your test, you can simply call it like this:
Post::factory()->count(20)->addComments()->create();
Upvotes: 4
Reputation: 17556
Updated: That should work: Inspired by apokryfos. If that not work, that will:
for($i=0; $i<20; $i++)
{
$times = rand(1,5);
Post::factory()
->has(Comment::factory()->times($times))
->create();
}
Upvotes: 2
Reputation: 40653
It's not possible to have a dynamic number of related models per model if you are using ->times
as far as I know. You can instead try:
collect(range(0,19))
->each(function () {
Post::factory()
->has(Comment::factory()->times(rand(1,5)))
->create();
});
This should create 20 posts one by one with a random number of comments on each. It may be a bit slower but probably not by much
Upvotes: 6