Skip to content

Getting Started

Requirements

  • PHP 8.3+
  • Laravel 11 or 12
  • A supported database (MySQL, MariaDB, PostgreSQL)

Installation

bash
composer require workflowable/workflowable

Publish and run the migrations:

bash
php artisan vendor:publish --tag="workflowable-migrations"
php artisan migrate

Publish the configuration file:

bash
php artisan vendor:publish --tag="workflowable-config"

Your First Workflow

1. Define a Workflow Event

Workflow events are pure DTOs that define what data a workflow carries. Workflows declare which event they respond to via an event_name column:

php
namespace App\WorkflowEvents;

use Workflowable\Workflowable\Abstracts\WorkflowEvent;

class OrderSubmitted extends WorkflowEvent
{
    public function __construct(
        public readonly int $orderId,
        public readonly float $amount,
        public readonly string $customerEmail,
    ) {}

    // Fields encrypted at rest
    public static function encrypted(): array
    {
        return ['customerEmail'];
    }
}

2. Create a Workflow Definition

Workflow definitions are stored as JSON in the database:

php
use Workflowable\Workflowable\Models\Workflow;

Workflow::create([
    'name' => 'order_processing',
    'event_name' => 'order_submitted',
    'definition' => [
        'name' => 'order_processing',
        'initial_step' => 'process_order',
        'steps' => [
            'process_order' => [
                'type' => 'action',
                'handler' => 'process_order',
            ],
            'check_amount' => [
                'type' => 'conditional',
                'handler' => 'is_high_value',
            ],
            'high_value_processing' => [
                'type' => 'action',
                'handler' => 'high_value_processing',
            ],
            'fulfill_order' => [
                'type' => 'action',
                'handler' => 'fulfill_order',
            ],
        ],
        'transitions' => [
            'process_order' => 'check_amount',
            'check_amount' => [
                'true' => 'high_value_processing',
                'false' => 'fulfill_order',
            ],
            'high_value_processing' => 'fulfill_order',
            'fulfill_order' => 'completed',
        ],
    ],
    'is_active' => true,
]);

3. Register Actions and Events

In config/workflowable.php:

php
return [
    'actions' => [
        'send_email' => \App\Actions\SendEmail::class,
    ],

    'conditionals' => [
        'is_high_value' => \App\Conditionals\IsHighValue::class,
    ],

    'events' => [
        'order_submitted' => [
            'class' => \App\WorkflowEvents\OrderSubmitted::class,
            'description' => 'Triggered when a new order is submitted',
            'actions' => [
                'process_order' => \App\Actions\ProcessOrder::class,
                'high_value_processing' => \App\Actions\HighValueProcessing::class,
                'fulfill_order' => \App\Actions\FulfillOrder::class,
            ],
        ],
    ],
];

4. Create Action Handlers

Action handlers receive the ExecutionContext with all workflow variables:

php
namespace App\Actions;

use Workflowable\Workflowable\Engine\ExecutionContext;

class ProcessOrder
{
    public function handle(ExecutionContext $context): array
    {
        $orderId = $context->getVariable('orderId');
        $amount = $context->getVariable('amount');

        // Your business logic...

        return ['processed' => true, 'receipt_id' => 'RCP-123'];
    }
}

The returned array is merged into the workflow's state, making it available to subsequent steps.

5. Dispatch the Workflow

Use the Workflowable facade to dispatch workflow events:

php
use Workflowable\Workflowable\Facades\Workflowable;

$event = new \App\WorkflowEvents\OrderSubmitted(
    orderId: 123,
    amount: 1500.00,
    customerEmail: 'customer@example.com',
);

// Async - dispatches ExecuteWorkflowJob to the queue
$instances = Workflowable::dispatch($event);

// Sync - executes inline, blocks until completion
$instances = Workflowable::dispatchSync($event);

Both methods return a Collection<WorkflowInstance> since one event can trigger multiple workflows.

6. Check Instance Status

php
foreach ($instances as $instance) {
    $instance->status;       // 'completed', 'pending', 'in_progress', 'failed'
    $instance->current_step; // null when completed, or the step name
}