State Machines
StateMachine\\HasTransitions
is useful when an enum represents a workflow with explicit allowed transitions.
What problem it solves
Without the trait, transition rules usually end up spread across match
expressions, guard methods, or service classes. HasTransitions
keeps that
behavior next to the enum cases, which makes the workflow easier to inspect and
test.
Example
<?php
declare(strict_types=1);
use FastForward\Enum\StateMachine\HasTransitions;
enum ArticleWorkflow: string
{
use HasTransitions;
case Draft = 'draft';
case Reviewing = 'reviewing';
case Published = 'published';
case Archived = 'archived';
protected static function transitionMap(): array
{
return [
self::Draft->name => [self::Reviewing, self::Archived],
self::Reviewing->name => [self::Published, self::Draft],
self::Published->name => [self::Archived],
self::Archived->name => [],
];
}
}
ArticleWorkflow::Draft->canTransitionTo(ArticleWorkflow::Reviewing); // true
What the trait adds
allowedTransitions()for the current casecanTransitionTo()andassertCanTransitionTo()for validationisTerminal()andterminalStates()for end statesisInitial()andinitialStates()for inferred or explicit entry points
When to use explicit initial states
If your workflow has more than one valid entry state, implement
initialStateCases()
directly. Otherwise the trait infers initial states by
finding cases with no incoming transitions.
When to avoid it
Do not force every state enum into a transition system. Use the trait only when the transitions are part of the public behavior you want to model.