Eloquent Model States: Workflow
Eloquent Model States: Workflow
Eloquent Model States: Workflow
Tip: State Column
$table->string('status')->default('draft');
Gotcha: State Transitions
public function publish(): void
{
if ($this->status !== 'draft') {
throw new Exception('Only drafts can be published');
}
$this->update(['status' => 'published']);
}
Tip: State Scope
public function scopeDraft(Builder $query): Builder
{
return $query->where('status', 'draft');
}
Gotcha: State Validation
protected static function booted(): void
{
static::updating(function ($post) {
$validTransitions = ['draft' => ['published', 'archived']];
// Validate transition
});
}
Tip: State Enum (PHP 8.1+)
enum PostStatus: string {
case Draft = 'draft';
case Published = 'published';
case Archived = 'archived';
}
Gotcha: State and Events
Fire events on state transitions for side effects.
Tip: Use cursor() for Memory-Neutral Iteration
When exporting 100K rows, get() loads everything into memory. cursor() uses yield and keeps memory flat regardless of row count. Perfect for artisan commands.
Tip: whereHas() vs load() — Two Different Things
whereHas() filters the parent query by relationship existence. load() eager-loads relationships AFTER the query. Mixing them up is a common source of logic bugs.
Gotcha: withCount() Adds a Subquery
withCount('comments') runs a correlated subquery on every row. On large tables, this can be slower than a separate query. Profile before relying on it.
Senior Insight
Model states are an elegant way to manage workflows, but I've seen them used where a simple status enum would suffice. State machines add complexity — transition rules, guard clauses, after-hooks — that's justified only when the workflow has genuinely complex rules (like order processing with cancellations, refunds, and chargebacks). For simple status values (draft/published/archived), use enums and avoid the overhead.
Source: Laravel Docs (https://laravel.com/docs/eloquent), Laravel News (https://laravel-news.com/), Freek.dev (https://freek.dev/tags/eloquent)