Skip to content

Factory states can accept arguments

Aug 20, 2026 1 min read #laravel #testing

Originally published on Mastering Laravel.

Most Eloquent factory states I’ve created are pretty simple like ->published() or ->cancelled(). They flip a flag or override a field to a fixed value making the call site of the factory easier to understand and requiring less ceremony. Awesome.

But, a state can also accept arguments, and that opens up some useful patterns like deriving values from another model passed in by the caller.

Imagine we had a scheduled event factory, and we want to use it to build chains of events, one hour after another. We might make a state like this:

public function fromEventOneHourLater(ScheduledEvent $source): self
{
  return $this->state([
    'start_at' => $source->start_at->addHour(),
    'timezone' => $source->timezone,
    'organizer_email' => $source->organizer_email,
  ]);
}
php

The state name says exactly what it does to the data. The argument is a model because the state needs to read three fields off it, one that gets transformed (start_at plus an hour) and two that get copied verbatim.

We can now build our chain in the test:

$first = ScheduledEvent::factory()->create();
$second = ScheduledEvent::factory()->fromEventOneHourLater($first)->create();
$third = ScheduledEvent::factory()->fromEventOneHourLater($second)->create();
php

Be careful not to take this too far, though. You should consider this as the facade PHP pattern for reducing your boilerplate test code, not for duplicating business logic.

I do contract work - and specialize in Laravel. If you need a hand, let me know.