Getting Started
Requirements
- PHP 8.3+
- Laravel 11 or 12
- A supported database (MySQL, MariaDB, PostgreSQL)
Installation
bash
composer require workflowable/workflowablePublish and run the migrations:
bash
php artisan vendor:publish --tag="workflowable-migrations"
php artisan migratePublish 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
}