Seeders & Factories
LaravelSeeders populate your database with data. Factories generate fake model instances. Together they let you set up a realistic development environment and write tests without manually inserting rows.
How They Work Together
| Tool | Purpose | Used For |
|---|---|---|
| Factory | Generates fake model data | Tests, seeders, quick prototyping |
| Seeder | Runs insert logic against the DB | Dev setup, demo data, initial records |
| Faker | Provides fake data values | Inside factories (names, emails, etc.) |
1. Creating a Factory
Terminal
# Generate a factory for the User model
php artisan make:factory UserFactory --model=User
# Generate a factory for a Post model
php artisan make:factory PostFactory --model=Postdatabase/factories/PostFactory.php
<?php
namespace Database\Factories;
use App\Models\User;
use Illuminate\Database\Eloquent\Factories\Factory;
class PostFactory extends Factory
{
public function definition(): array
{
return [
'user_id' => User::factory(),
'title' => fake()->sentence(6),
'slug' => fake()->unique()->slug(),
'body' => fake()->paragraphs(4, true),
'status' => fake()->randomElement(['draft', 'published']),
'published_at' => fake()->optional()->dateTimeBetween('-1 year', 'now'),
];
}
}2. Useful Faker Methods
| Faker method | Example output |
|---|---|
fake()->name() | Jane Smith |
fake()->email() | user@example.com |
fake()->sentence(5) | The quick brown fox jumps. |
fake()->paragraphs(3, true) | Multi-paragraph string |
fake()->numberBetween(1, 100) | 42 |
fake()->randomElement(['a','b']) | a or b |
fake()->unique()->slug() | lorem-ipsum-dolor (unique) |
fake()->optional() | Value or null (70/30 chance) |
fake()->dateTimeBetween('-1 year', 'now') | A DateTime object |
fake()->imageUrl(640, 480) | https://via.placeholder.com/... |
3. Factory States
States let you define named variations of a factory:
database/factories/PostFactory.php
public function definition(): array
{
return [
'title' => fake()->sentence(),
'status' => 'draft',
];
}
public function published(): static
{
return $this->state(fn (array $attrs) => [
'status' => 'published',
'published_at' => now(),
]);
}
public function withLongTitle(): static
{
return $this->state(fn (array $attrs) => [
'title' => fake()->sentence(20),
]);
}Using States
// Draft post (default)
Post::factory()->create();
// Published post
Post::factory()->published()->create();
// Published post with long title
Post::factory()->published()->withLongTitle()->create();4. Creating a Seeder
Terminal
php artisan make:seeder PostSeederdatabase/seeders/PostSeeder.php
<?php
namespace Database\Seeders;
use App\Models\Post;
use App\Models\User;
use Illuminate\Database\Seeder;
class PostSeeder extends Seeder
{
public function run(): void
{
// Create 5 users, each with 10 posts
User::factory(5)->create()->each(function (User $user) {
Post::factory(10)->create(['user_id' => $user->id]);
});
// Create 3 published posts specifically
Post::factory(3)->published()->create();
}
}5. DatabaseSeeder — the Entry Point
database/seeders/DatabaseSeeder.php
<?php
namespace Database\Seeders;
use Illuminate\Database\Seeder;
class DatabaseSeeder extends Seeder
{
public function run(): void
{
$this->call([
UserSeeder::class,
PostSeeder::class,
]);
}
}6. Running Seeders
Terminal
# Run all seeders (DatabaseSeeder)
php artisan db:seed
# Run a specific seeder
php artisan db:seed --class=PostSeeder
# Fresh migration + seed in one command
php artisan migrate:fresh --seed7. Using Factories in Tests
Factories are most powerful in tests — no manual DB setup needed:
tests/Feature/PostTest.php
<?php
namespace Tests\Feature;
use App\Models\Post;
use App\Models\User;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;
class PostTest extends TestCase
{
use RefreshDatabase;
public function test_user_can_view_published_posts(): void
{
// Create 3 published and 2 draft posts
Post::factory(3)->published()->create();
Post::factory(2)->create(); // draft
$response = $this->getJson('/api/posts');
$response->assertOk()
->assertJsonCount(3, 'data');
}
public function test_authenticated_user_can_create_post(): void
{
$user = User::factory()->create();
$this->actingAs($user)->postJson('/api/posts', [
'title' => 'My Post',
'body' => 'Some content here.',
])->assertCreated();
$this->assertDatabaseHas('posts', ['title' => 'My Post']);
}
}8. Factory Relationships
Creating Related Models
// Create a post with its author auto-created
$post = Post::factory()->create();
// Create a post belonging to a specific user
$user = User::factory()->create();
$post = Post::factory()->create(['user_id' => $user->id]);
// Create a user with 5 posts using has()
$user = User::factory()
->has(Post::factory()->count(5), 'posts')
->create();
// Create posts with their author using for()
$posts = Post::factory(10)
->for(User::factory()->create(), 'author')
->create();💡
RefreshDatabase in tests. Always add
use RefreshDatabase; to test classes that hit the database — it wraps each test in a transaction and rolls it back, keeping tests isolated and fast.⚠️
Never run seeders in production with fake data. Use
--env=local or guard your seeders with an environment check: if (app()->isProduction()) return;Test your knowledge!
Take the Laravel quiz.