solution-forest / workflow-engine-laravel
Laravel integration for the Workflow Engine - providing Eloquent models, service providers, and artisan commands for seamless workflow management
Fund package maintenance!
solutionforest
Requires
- php: ^8.3
- illuminate/contracts: ^10.0||^11.0||^12.0
- illuminate/database: ^10.0||^11.0||^12.0
- illuminate/events: ^10.0||^11.0||^12.0
- illuminate/support: ^10.0||^11.0||^12.0
- solution-forest/workflow-engine-core: ^0.0.2-alpha
Requires (Dev)
- larastan/larastan: ^2.9||^3.0
- laravel/pint: ^1.14
- nunomaduro/collision: ^8.1.1||^7.10.0
- orchestra/testbench: ^9.0.0|^10.0.0
- pestphp/pest: ^3.0
- pestphp/pest-plugin-arch: ^3.0
- pestphp/pest-plugin-laravel: ^3.0
- phpstan/extension-installer: ^1.3||^2.0
- phpstan/phpstan-deprecation-rules: ^1.1||^2.0
- phpstan/phpstan-phpunit: ^1.3||^2.0
- spatie/laravel-ray: ^1.35
Conflicts
- laravel/framework: <11.0.0
This package is not auto-updated.
Last update: 2025-05-30 12:23:34 UTC
README
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' => 'john@example.com'] ]); // Or use the helper functions $workflowId = start_workflow('user-onboarding-002', $definition, [ 'user' => ['name' => 'Jane Doe', 'email' => 'jane@example.com'] ]);
💼 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' => 'jane@example.com'] ]);
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'] ?? 'default@example.com'; $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' => 'john@example.com', '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
- Getting Started Guide - Complete setup and basic usage
- API Reference - Detailed API documentation
- Advanced Features - Error handling, timeouts, retries
- Best Practices - Performance tips and patterns
- Migration Guide - Upgrading from older versions
- Architecture - Technical implementation details
🧪 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.