Defining Model Factories

A factory describes one plausible row. php artisan make:factory ProductFactory writes the class to database/factories, and the model's HasFactory trait finds it by name (#[UseFactory] overrides that). definition() returns attributes built with fake(), the FakerPHP 3,995 (https://github.com/FakerPHP/Faker 3,995 ) generator (1.24.1, a require-dev package) in the APP_FAKER_LOCALE locale:

The definition() method of ProductFactoryPHP
return [
    'sku' => Str::upper(fake()->unique()->bothify('BK-????-##')),
    'isbn' => fake()->unique()->isbn13(),
    'title' => Str::title(fake()->words(3, true)),
    'category_id' => Category::factory(),
    'price' => fake()->randomFloat(2, 5, 60),
    'stock' => fake()->numberBetween(1, 50),
    'attributes' => ['format' => fake()->randomElement(['paperback', 'ebook']),
                     'pages' => fake()->numberBetween(120, 600)],
];

make() builds unsaved models, create() inserts them and raw() returns the array. A factory used as a value, like Category::factory(), creates the parent row, even under make(). On an empty database, in php artisan tinker:

make() still inserts the parentSQL
use App\Models\{Category, Product};
echo json_encode(Product::factory()->make()->only('sku', 'category_id', 'price')), "\n";
echo 'categories: ', Category::count(), "\n";
echo 'without: ', var_export(Product::factory()->withoutParents()->make()->category_id, true);
Output
{"sku":"BK-VGQZ-57","category_id":1,"price":"16.52"}
categories: 1
without: NULL

withoutParents() keeps unit tests off the database. Because composer install --no-dev removes Faker, factories belong only in seeders that never run in production.