Stage 3

Factories and Seeders

Create factories for all models and seed the database with test data.

Task

In this stage, you'll create factories for all models and seed the database with realistic test data. This will allow you to test your application with a substantial amount of data.

Requirements

  • Create realistic factories for all models
  • Seed with:
    • 10 users
    • 5 parent categories
    • 15 child categories
    • 50 products
    • 30 orders
    • 100 order items
    • 80 reviews
    • 20 wishlist items

Implementation Steps

1. Create factories for each model

php artisan make:factory CategoryFactory
php artisan make:factory ProductFactory
php artisan make:factory OrderFactory
php artisan make:factory OrderItemFactory
php artisan make:factory ReviewFactory
php artisan make:factory WishlistFactory

2. Implement the Category factory

database/factories/CategoryFactory.php
php
<?php
namespace Database\Factories;
use App\Models\Category;
use Illuminate\Database\Eloquent\Factories\Factory;
class CategoryFactory extends Factory
{
protected $model = Category::class;
public function definition(): array
{
// TODO: Define the default state for a Category
// This should return an array with:
// - name: a random word
// - description: a random paragraph
// - parent_id: null (for parent categories)
return [
// Your code here...
];
}
// TODO: Create a child method that sets a random parent_id
// This should return a state where parent_id is set to a random Category id
public function child(): static
{
// Your code here...
}
}

3. Implement the Product factory

database/factories/ProductFactory.php
php
<?php
namespace Database\Factories;
use App\Models\Category;
use App\Models\Product;
use Illuminate\Database\Eloquent\Factories\Factory;
class ProductFactory extends Factory
{
protected $model = Product::class;
public function definition(): array
{
// TODO: Define the default state for a Product
// This should return an array with:
// - name: a random product name (e.g., 3 random words)
// - description: a random paragraph
// - price: a random float between 10 and 1000 with 2 decimal places
// - stock_quantity: a random number between 0 and 100
// - category_id: a random Category id
return [
// Your code here...
];
}
}

4. Create a database seeder

Implement the DatabaseSeeder to create all the required data:

database/seeders/DatabaseSeeder.php
php
<?php
namespace Database\Seeders;
use App\Models\Category;
use App\Models\Order;
use App\Models\OrderItem;
use App\Models\Product;
use App\Models\Review;
use App\Models\User;
use App\Models\Wishlist;
use Illuminate\Database\Seeder;
class DatabaseSeeder extends Seeder
{
public function run(): void
{
// TODO: Create 10 users
// TODO: Create 5 parent categories
// TODO: Create 15 child categories
// TODO: Create 50 products with random categories
// TODO: Create 30 orders with random users
// TODO: For each order, create 1-5 order items with random products
// Don't forget to update the order's total_amount based on the items
// TODO: Create 80 reviews with random users and products
// TODO: Create 20 wishlist items with random users and products
// Your code here...
}
}

Hint:

Use the following patterns for creating model instances:

  • User::factory(10)->create()to create 10 users
  • Category::factory(5)->create()to create 5 parent categories
  • Category::factory(15)->child()->create()to create 15 child categories
  • $users->random()->idto get a random user ID
  • For order items, calculate the total amount by multiplying quantity by unit price

5. Run the seeder

php artisan db:seed

Checkpoint 3

Add this route to your routes/web.php:

routes/web.php
php
Route::get('/check-seeding', function () {
$counts = [
'Users' => \App\Models\User::count(),
'Categories' => \App\Models\Category::count(),
'Products' => \App\Models\Product::count(),
'Orders' => \App\Models\Order::count(),
'OrderItems' => \App\Models\OrderItem::count(),
'Reviews' => \App\Models\Review::count(),
'Wishlists' => \App\Models\Wishlist::count(),
];
$randomData = [
'Random User' => \App\Models\User::inRandomOrder()->first(),
'Random Product' => \App\Models\Product::with('category')->inRandomOrder()->first(),
'Random Order' => \App\Models\Order::with('orderItems')->inRandomOrder()->first(),
];
return [
'counts' => $counts,
'samples' => $randomData
];
});

Visit /check-seeding and share a screenshot of the output on Slack. The output should show the counts of all your seeded data.