Model factories — definition(), states, sequences
Concept
Model factories are classes that know how to generate realistic fake instances of your Eloquent models. Every factory extends Illuminate\Database\Eloquent\Factories\Factory and implements a single required method, definition(), which returns an array of default attribute values. Laravel wires a factory to its model via the HasFactory trait, which adds the static factory() method to every model and uses a naming convention — App\Models\Post maps to Database\Factories\PostFactory — to resolve the right class without any registration.
The definition() method receives a $this->faker instance (a Faker\Generator) that you use to generate realistic data. Each call to factory() creates a new Faker\Generator seeded from config('app.faker_seed'), so results are random by default but reproducible in tests when you fix the seed. The factory itself is a value object: calling factory() returns a Factory instance and nothing is written to the database until you call create() or createMany().
States are named variations of a factory's definition(). You define them by adding methods that return $this->state(fn (array $attributes) => [...]). States compose cleanly — User::factory()->admin()->suspended()->create() merges the state arrays in order, with later states winning on key conflicts. This composability lets you describe complex scenarios (->banned()->withExpiredSubscription()) without building separate factory classes.
Sequences let you cycle through a set of values across multiple model instances. $this->sequence(['role' => 'admin'], ['role' => 'editor'], ['role' => 'viewer']) assigns roles in rotation when you call factory()->count(9)->create(). You can also pass a closure to sequence() for computed values that depend on the current index.
| Factory method | Returns | Persists to DB |
|---|---|---|
make() | Model instance | No |
create() | Model instance | Yes |
makeMany(n) | Collection | No |
createMany(n) | Collection | Yes |
raw() | Plain array | No |
Code Example
<?php
namespace Database\Factories;
use App\Models\User;
use Illuminate\Database\Eloquent\Factories\Factory;
use Illuminate\Support\Str;
/**
* @extends Factory<User>
*/
class UserFactory extends Factory
{
// Override if the naming convention doesn't apply
protected $model = User::class;
public function definition(): array
{
return [
'name' => fake()->name(),
'email' => fake()->unique()->safeEmail(),
'email_verified_at' => now(),
'password' => bcrypt('password'), // fixed for dev convenience
'remember_token' => Str::random(10),
];
}
// --- States ---
/** Admin user with elevated role flag */
public function admin(): static
{
return $this->state(fn (array $attributes) => [
'role' => 'admin',
]);
}
/** Unverified user — email_verified_at is null */
public function unverified(): static
{
return $this->state(fn (array $attributes) => [
'email_verified_at' => null,
]);
}
/** Suspended user */
public function suspended(): static
{
return $this->state(fn (array $attributes) => [
'suspended_at' => now()->subDays(7),
]);
}
// --- Sequence example ---
/** Rotate through three roles for a batch */
public function withRotatingRoles(): static
{
return $this->sequence(
['role' => 'admin'],
['role' => 'editor'],
['role' => 'viewer'],
);
}
}
// Usage in a test or seeder:
// User::factory()->count(3)->withRotatingRoles()->create();
// User::factory()->admin()->unverified()->make(); // no DB writeInterview Q&A
Q: How does the HasFactory trait locate the correct factory class for a model?
HasFactory::factory() calls the static newFactory() method, which by default uses Factory::resolveFactoryName(static::class). That resolver strips the App\Models\ namespace prefix, prepends Database\Factories\, and appends Factory — so App\Models\BlogPost resolves to Database\Factories\BlogPostFactory. You can override newFactory() on the model to return a specific factory instance when your project's namespace or directory structure doesn't match the convention. This design means zero registration overhead for the common case.
Q: What is the difference between a factory state and overriding attributes directly in create()?
Both merge attributes over the definition(), but states are reusable, named, and composable: you can chain multiple states and they read like a specification (->admin()->suspended()). Direct attribute overrides in create(['role' => 'admin']) are one-shot and not reusable across tests. Use states whenever the same combination of attributes appears in more than one test, and use inline overrides for truly one-off values like a specific email address for a known test case.
Q: How do sequences differ from states, and when would you prefer one over the other?
A state always produces the same fixed attribute values — it describes a stable variant. A sequence cycles through a list of attribute sets across multiple instances created in a single factory()->count(n) call, making it ideal for distributing varied but predictable data (e.g., alternating statuses, rotating roles, incrementing dates). Use a state when you need a named, documented variant of a model; use a sequence when you need controlled variety across a batch of records without writing a loop.