Reputation: 6386
I have two factories one for categories and another for products. When I run the factory I want to create x number of products for each category generated. how would I write the code to product this?
the definition for the categories is written as this:
return [
'name' => $this->faker->word,
'slug' => Str::slug($this->faker->unique()->word, '-'),
];
and the definition for the product is written as such:
return [
'category_id' => 1, //instead of 1 the category id used i want to be random
'name' => $this->faker->word,
'slug' => Str::slug($this->faker->unique()->word, '-'),
'description' => $this->faker->paragraph,
'price' => $this->faker->randomFloat(2, 0, 10000),
'is_visible' => 1,
'is_featured' => 1
];
as you can see I hardcoded the category_id
, I wasnt too sure how to have it automatically generate and create a product per category that exists. I have the factory for the category written as this, to create 10 items
Category::factory()
->count(10)
->create();
I tried this for trial and error thinking it would work but I get an error that category_id cannot be null
.
Product::factory()
->has(Category::factory()->count(2))
->count(20)
->create();
Upvotes: 2
Views: 5154
Reputation: 145
$factory->define(Product::class, function (Faker $faker) {
return [
'category_id' => factory(Category::class), //instead of 1 the category id used i want to be random
'name' => $this->faker->word,
'slug' => Str::slug($this->faker->unique()->word, '-'),
'description' => $this->faker->paragraph,
'price' => $this->faker->randomFloat(2, 0, 10000),
'is_visible' => 1,
'is_featured' => 1
];
});
For more info, see the source of this copied quote:
By setting the attribute to an instance of factory() Laravel will lazily create that model as well and automatically associate it
-- https://www.dwightwatson.com/posts/building-relations-with-laravel-model-factories
Upvotes: 2
Reputation: 1
use Illuminate\Support\Str;
public function definition(): array
{
return [
'category_id'=>'1',
'title'=> $this->faker->text(20),
'slug' => function ($attr) {
return Str::slug($attr['title']);
},
'content'=> $this->faker->realText($maxNbChars = 200, $indexSize = 2),
'is_published'=> $this->faker->boolean()
];
}
Upvotes: 0
Reputation: 2730
If you want to create multiple products per each created category, you can do something like this:
// CategoryProductSeeder
$categories = Category::factory(50)->create();
$categories->each(function ($category) {
$categories->products()->saveMany(
Product::factory(10)->make()
);
});
Upvotes: 1
Reputation: 14921
You simply need to pass a CategoryFactory
to category_id
.
return [
'category_id' => Category::factory(),
// ...
];
You can read more about factories here: https://laravel.com/docs/8.x/database-testing#defining-relationships-within-factories
Upvotes: 1
Reputation: 6386
this is what worked for me since I'm using laravel 8.
product definition:
return [
'category_id' => Category::factory(),
'name' => $this->faker->word,
'slug' => Str::slug($this->faker->unique()->word, '-'),
'description' => $this->faker->paragraph,
'price' => $this->faker->randomFloat(2, 0, 1000),
'is_visible' => 1,
'is_featured' => 1
];
seeder:
Product::factory()
->has(Category::factory())->count(50)
->create();
created 50 categories and 50 products. 1 category assigned to each product.
Upvotes: 0
Reputation: 542
I am using kind of different syntax, but I think it will work / you can change it
In your Category.php
model
public function products() {
return $this->hasMany(Product::class);
}
In seeder
factory(App\Category::class, 10)->create()->each(function($c) {
$c->products()->save(factory(App\Product::class)->make());
}); // each Category will have 1 product
Laravel Database Testing Relationships
Upvotes: 2