Skip to content

A flexible and powerful workflow engine for Laravel applications. Build, manage, and execute complex business processes with ease using a declarative workflow definition system. Features include conditional branching, parallel execution, state management, and comprehensive logging.

License

Notifications You must be signed in to change notification settings

solutionforest/workflow-engine-laravel

Repository files navigation

Laravel Workflow Engine

Latest Version on Packagist GitHub Tests Action Status Total Downloads

A modern, type-safe workflow engine for Laravel built with PHP 8.3+ features

Create powerful business workflows with simple, maintainable code.

⚠️ WARNING: DEVELOPMENT STATUS⚠️

This package is currently under active development and is NOT READY FOR PRODUCTION USE.

Features may be incomplete, APIs might change, and there could be breaking changes. Use at your own risk in development environments only.

✨ Why Choose This Workflow Engine?

  • 🎨 Simple & Intuitive - Array-based workflow definitions and fluent WorkflowBuilder API
  • 🏷️ Modern PHP 8.3+ Attributes - Declarative configuration with #[WorkflowStep], #[Retry], #[Timeout]
  • πŸ”’ Type Safety First - Built with enums, strong typing, and modern PHP features
  • ⚑ Laravel Native - Seamless integration with Laravel's ecosystem and helpers
  • 🧩 Extensible - Easy to extend with custom actions and storage adapters
  • πŸ“š Well Tested - Comprehensive test suite with real-world examples

πŸš€ Quick Start

Installation

composer require solution-forest/workflow-engine-laravel

Optionally publish the config file:

php artisan vendor:publish --tag="workflow-engine-config"

For database storage, run the migrations:

php artisan migrate

The migration will create a workflow_instances table to store workflow state and progress.

Your First Workflow in 30 Seconds

use SolutionForest\WorkflowEngine\Core\WorkflowEngine;

// Create a simple workflow definition
$definition = [
    'name' => 'User Onboarding',
    'version' => '1.0',
    'steps' => [
        [
            'id' => 'welcome',
            'name' => 'Send Welcome',
            'action' => 'log',
            'parameters' => [
                'message' => 'Welcome {{ user.name }}!',
                'level' => 'info'
            ]
        ],
        [
            'id' => 'setup',
            'name' => 'Setup Account', 
            'action' => 'log',
            'parameters' => [
                'message' => 'Setting up account for {{ user.email }}',
                'level' => 'info'
            ]
        ]
    ]
];

// Start the workflow using the engine
$workflowId = workflow()->start('user-onboarding-001', $definition, [
    'user' => ['name' => 'John Doe', 'email' => '[email protected]']
]);

// Or use the helper functions
$workflowId = start_workflow('user-onboarding-002', $definition, [
    'user' => ['name' => 'Jane Doe', 'email' => '[email protected]']
]);

πŸ’Ό Real-World Examples

E-commerce Order Processing

$definition = [
    'name' => 'Order Processing',
    'version' => '1.0',
    'steps' => [
        [
            'id' => 'validate-order',
            'name' => 'Validate Order',
            'action' => 'log',
            'parameters' => [
                'message' => 'Validating order {{ order.id }}',
                'level' => 'info'
            ]
        ],
        [
            'id' => 'process-payment',
            'name' => 'Process Payment',
            'action' => 'log',
            'parameters' => [
                'message' => 'Processing payment for {{ order.total }}',
                'level' => 'info'
            ]
        ],
        [
            'id' => 'fulfill-order',
            'name' => 'Fulfill Order',
            'action' => 'log',
            'parameters' => [
                'message' => 'Order {{ order.id }} fulfilled',
                'level' => 'info'
            ]
        ]
    ]
];

$workflowId = start_workflow('order-001', $definition, [
    'order' => ['id' => 'ORD-001', 'total' => 99.99]
]);

Document Approval Process

$definition = [
    'name' => 'Document Approval',
    'version' => '1.0',
    'steps' => [
        [
            'id' => 'submit',
            'name' => 'Submit Document',
            'action' => 'log',
            'parameters' => [
                'message' => 'Document {{ document.id }} submitted by {{ user.name }}',
                'level' => 'info'
            ]
        ],
        [
            'id' => 'review',
            'name' => 'Manager Review',
            'action' => 'log',
            'parameters' => [
                'message' => 'Document {{ document.id }} under review',
                'level' => 'info'
            ]
        ],
        [
            'id' => 'approve',
            'name' => 'Final Approval',
            'action' => 'log',
            'parameters' => [
                'message' => 'Document {{ document.id }} approved',
                'level' => 'info'
            ]
        ]
    ]
];

$workflowId = start_workflow('doc-approval-001', $definition, [
    'document' => ['id' => 'DOC-001'],
    'user' => ['name' => 'John Doe']
]);

User Onboarding

$definition = [
    'name' => 'User Onboarding',
    'version' => '1.0',
    'steps' => [
        [
            'id' => 'welcome',
            'name' => 'Send Welcome Message',
            'action' => 'log',
            'parameters' => [
                'message' => 'Welcome {{ user.name }}! Starting onboarding...',
                'level' => 'info'
            ]
        ],
        [
            'id' => 'setup-profile',
            'name' => 'Setup User Profile',
            'action' => 'log',
            'parameters' => [
                'message' => 'Setting up profile for {{ user.email }}',
                'level' => 'info'
            ]
        ],
        [
            'id' => 'complete',
            'name' => 'Complete Onboarding',
            'action' => 'log',
            'parameters' => [
                'message' => 'Onboarding complete for {{ user.name }}',
                'level' => 'info'
            ]
        ]
    ]
];

$workflowId = start_workflow('onboarding-001', $definition, [
    'user' => ['name' => 'Jane Doe', 'email' => '[email protected]']
]);

Creating Custom Actions

<?php

namespace App\Actions;

use SolutionForest\WorkflowEngine\Contracts\WorkflowAction;
use SolutionForest\WorkflowEngine\Core\ActionResult;
use SolutionForest\WorkflowEngine\Core\WorkflowContext;

class SendEmailAction implements WorkflowAction
{
    private array $config;
    
    public function __construct(array $config = [])
    {
        $this->config = $config;
    }
    
    public function execute(WorkflowContext $context): ActionResult
    {
        $to = $this->config['to'] ?? '[email protected]';
        $subject = $this->config['subject'] ?? 'Notification';
        
        // Process template variables
        $processedTo = $this->processTemplate($to, $context->getData());
        $processedSubject = $this->processTemplate($subject, $context->getData());
        
        // Send email using Laravel's Mail facade
        Mail::to($processedTo)->send(new WorkflowNotification($processedSubject));
        
        return ActionResult::success([
            'email_sent' => true,
            'recipient' => $processedTo
        ]);
    }
    
    private function processTemplate(string $template, array $data): string
    {
        return preg_replace_callback('/\{\{\s*([^}]+)\s*\}\}/', function ($matches) use ($data) {
            $key = trim($matches[1]);
            return data_get($data, $key, $matches[0]);
        }, $template);
    }
}

Then use it in your workflows:

$definition = [
    'name' => 'Email Workflow',
    'steps' => [
        [
            'id' => 'send-email',
            'action' => SendEmailAction::class,
            'parameters' => [
                'to' => '{{ user.email }}',
                'subject' => 'Welcome {{ user.name }}!'
            ]
        ]
    ]
];

πŸ”§ Core Features

Modern PHP 8.3+ Attributes

Enhance your workflow actions with declarative attributes for configuration:

<?php

namespace App\Actions;

use SolutionForest\WorkflowEngine\Attributes\WorkflowStep;
use SolutionForest\WorkflowEngine\Attributes\Timeout;
use SolutionForest\WorkflowEngine\Attributes\Retry;
use SolutionForest\WorkflowEngine\Attributes\Condition;
use SolutionForest\WorkflowEngine\Contracts\WorkflowAction;
use SolutionForest\WorkflowEngine\Core\ActionResult;
use SolutionForest\WorkflowEngine\Core\WorkflowContext;

#[WorkflowStep(
    id: 'send_email',
    name: 'Send Welcome Email',
    description: 'Sends a welcome email to new users'
)]
#[Timeout(minutes: 5)]
#[Retry(attempts: 3, backoff: 'exponential')]
#[Condition('user.email is not null')]
class SendWelcomeEmailAction implements WorkflowAction
{
    public function execute(WorkflowContext $context): ActionResult
    {
        $user = $context->getData('user');
        
        // Send email logic here
        Mail::to($user['email'])->send(new WelcomeEmail($user));
        
        return ActionResult::success(['email_sent' => true]);
    }
}

Available Attributes:

  • #[WorkflowStep] - Define step metadata (id, name, description, config)
  • #[Timeout] - Set execution timeouts (seconds, minutes, hours)
  • #[Retry] - Configure retry behavior (attempts, backoff strategy, delays)
  • #[Condition] - Add conditional execution rules

WorkflowBuilder Fluent API

Create workflows with an intuitive, chainable API:

use SolutionForest\WorkflowEngine\Core\WorkflowBuilder;

$workflow = WorkflowBuilder::create('user-onboarding')
    ->description('Complete user onboarding process')
    ->addStep('welcome', SendWelcomeEmailAction::class)
    ->addStep('setup', SetupUserAction::class, ['template' => 'premium'])
    ->when('user.plan === "premium"', function($builder) {
        $builder->addStep('premium-setup', PremiumSetupAction::class);
    })
    ->email('tips-email', '{{ user.email }}', 'Getting Started Tips')
    ->delay(hours: 24)
    ->addStep('complete', CompleteOnboardingAction::class)
    ->build();

// Start the workflow
$workflowId = $workflow->start('user-001', [
    'user' => ['email' => '[email protected]', 'plan' => 'premium']
]);

Modern PHP 8.3+ Enums

use SolutionForest\WorkflowEngine\Core\WorkflowState;

// Rich, type-safe workflow states
$state = WorkflowState::RUNNING;
echo $state->color();     // 'blue'
echo $state->icon();      // '▢️'
echo $state->label();     // 'Running'

// Smart state transitions
if ($state->canTransitionTo(WorkflowState::COMPLETED)) {
    workflow()->complete($workflowId);
}

Template Processing

// Use template variables in your workflow steps
$definition = [
    'name' => 'User Notification',
    'steps' => [
        [
            'id' => 'notify',
            'action' => 'log',
            'parameters' => [
                'message' => 'Hello {{ user.name }}, your order {{ order.id }} is ready!',
                'level' => 'info'
            ]
        ]
    ]
];

start_workflow('notification-001', $definition, [
    'user' => ['name' => 'John'],
    'order' => ['id' => 'ORD-123']
]);

Built-in Actions

// Log Action - Built-in logging with template support
[
    'id' => 'log-step',
    'action' => 'log',
    'parameters' => [
        'message' => 'Processing {{ item.name }}',
        'level' => 'info'
    ]
]

// Delay Action - Built-in delays (for testing/demo)
[
    'id' => 'delay-step', 
    'action' => 'delay',
    'parameters' => [
        'seconds' => 2
    ]
]

Workflow Management

// Start workflows
$workflowId = start_workflow('my-workflow', $definition, $context);

// Get workflow status
$instance = get_workflow($workflowId);
echo $instance->getState()->label(); // Current state

// List all workflows
$workflows = list_workflows();

// Filter workflows by state
$runningWorkflows = list_workflows(['state' => WorkflowState::RUNNING]);

// Cancel a workflow
cancel_workflow($workflowId, 'User requested cancellation');

Helper Functions

The package provides convenient helper functions for common operations:

// Get the workflow engine instance
$engine = workflow();

// Start a workflow
$workflowId = start_workflow('my-workflow-id', $definition, $context);

// Get a workflow instance  
$instance = get_workflow('my-workflow-id');

// List all workflows
$workflows = list_workflows();

// List workflows filtered by state
$runningWorkflows = list_workflows(['state' => WorkflowState::RUNNING]);

// Cancel a workflow
cancel_workflow('my-workflow-id', 'User cancelled');

πŸ“– Documentation

πŸ§ͺ Testing

composer test

πŸ“ Changelog

Please see CHANGELOG for more information on what has changed recently.

🀝 Contributing

Please see CONTRIBUTING for details.

πŸ”’ Security Vulnerabilities

Please review our security policy on how to report security vulnerabilities.

πŸ“„ License

The MIT License (MIT). Please see License File for more information.

About

A flexible and powerful workflow engine for Laravel applications. Build, manage, and execute complex business processes with ease using a declarative workflow definition system. Features include conditional branching, parallel execution, state management, and comprehensive logging.

Topics

Resources

License

Stars

Watchers

Forks

Sponsor this project

Languages