Laravel Stateflow Demo

January 14, 2026 · View on GitHub

This demo application showcases Laravel Stateflow — a powerful state machine package for Laravel. It demonstrates two different approaches to configuring state workflows using real-world examples.

Overview

ModelApproachDescription
OrderTraditionalState transitions defined explicitly using allowTransition() calls
BookingHybrid EnumTransition topology defined in an enum, behavior in state classes

1. Orders — Traditional Approach

The Order model demonstrates the traditional approach where state classes and transitions are configured explicitly in the model's registerStates() method.

State Topology

┌─────────┐     ┌────────────┐     ┌─────────┐     ┌───────────┐
│ Pending │────▶│ Processing │────▶│ Shipped │────▶│ Delivered │
└─────────┘     └────────────┘     └─────────┘     └───────────┘
     │                │
     │                │
     ▼                ▼
┌───────────┐   ┌───────────┐
│ Cancelled │◀──│           │
└───────────┘   └───────────┘

Allowed Transitions

FromTo
PendingProcessing
PendingCancelled
ProcessingShipped
ProcessingCancelled
ShippedDelivered

Configuration

// app/Models/Order.php
public static function registerStates(): void
{
    static::addState('state', StateConfig::make(OrderState::class)
        ->default(Pending::class)
        ->registerStates([
            Pending::class,
            Processing::class,
            Shipped::class,
            Delivered::class,
            Cancelled::class,
        ])
        ->allowTransition(Pending::class, Processing::class)
        ->allowTransition(Pending::class, Cancelled::class)
        ->allowTransition(Processing::class, Shipped::class)
        ->allowTransition(Processing::class, Cancelled::class)
        ->allowTransition(Shipped::class, Delivered::class)
    );
}

Key Files


2. Bookings — Hybrid Enum Approach

The Booking model demonstrates the hybrid approach where the transition topology is defined in an enum (BookingWorkflow), while behavior and metadata remain in state classes.

State Topology

┌───────┐     ┌───────────┐     ┌──────┐     ┌───────────┐
│ Draft │────▶│ Confirmed │────▶│ Paid │────▶│ Fulfilled │
└───────┘     └───────────┘     └──────┘     └───────────┘
     │              │                │
     │              │                │
     ▼              ▼                ▼
┌─────────┐   ┌───────────┐   ┌───────────┐
│ Expired │   │ Cancelled │◀──│           │
└─────────┘   │  Expired  │   └───────────┘
              └───────────┘

Allowed Transitions

FromTo
DraftConfirmed
DraftExpired
ConfirmedPaid
ConfirmedCancelled
ConfirmedExpired
PaidFulfilled
PaidCancelled (refund)

Configuration

The enum defines the transition topology:

// app/Enums/BookingStateStatus.php
enum BookingWorkflow: string
{
    case Draft = 'draft';
    case Confirmed = 'confirmed';
    case Paid = 'paid';
    case Fulfilled = 'fulfilled';
    case Cancelled = 'cancelled';
    case Expired = 'expired';

    public function canTransitionTo(): array
    {
        return match ($this) {
            self::Draft => [Confirmed::class, Expired::class],
            self::Confirmed => [Paid::class, Cancelled::class, Expired::class],
            self::Paid => [Fulfilled::class, Cancelled::class],
            // Final states
            self::Fulfilled, self::Cancelled, self::Expired => [],
        };
    }

    public static function transitions(): array
    {
        // Generates array for allowTransitionsFromArray()
    }
}

The model uses the enum for configuration:

// app/Models/Booking.php
public static function registerStates(): void
{
    static::addState('state', StateConfig::make(BookingState::class)
        ->default(Draft::class)
        ->registerStates(BookingWorkflow::stateClasses())
        ->allowTransitionsFromArray(BookingWorkflow::transitions())
    );
}

Key Files


Approach Comparison

AspectTraditional (Order)Hybrid Enum (Booking)
Topology DefinitionIn model's registerStates()In dedicated enum
State ClassesRequired for behaviorRequired for behavior
TransitionsallowTransition() callsallowTransitionsFromArray()
ReusabilityTied to modelEnum can be shared/documented
TestabilityTest via modelCan unit test enum independently
VisualizationRead from modelEnum is self-documenting

When to Use Each Approach

Traditional Approach

  • Simple workflows with few states
  • Transitions tightly coupled to model logic
  • Quick prototyping

Hybrid Enum Approach

  • Complex workflows with many states
  • Need clear separation of topology and behavior
  • Want self-documenting transition rules
  • Team prefers enum-based architecture

Learn More

Running the Demo

# Install dependencies
composer install
npm install

# Run migrations
php artisan migrate

# Seed sample data
php artisan db:seed

# Start the development server
composer run dev