Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Workflower Laravel Package

phpmentors/workflower

Workflower is an open-source BPMN 2.0 workflow engine for PHP. Import BPMN process definitions and run process instances with tasks, events, gateways, lanes, and sequence flows, plus interfaces for persistence via serialization/deserialization.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup in Laravel

  1. Install the Package

    composer require phpmentors/workflower "1.4.*"
    
  2. Define a BPMN Workflow

    • Create a .bpmn file (e.g., loan_request.bpmn) in resources/config/workflower/.
    • Use tools like Camunda Modeler to design workflows with supported elements (tasks, gateways, events, etc.).
    • Ensure conditional expressions use Symfony's ExpressionLanguage syntax (e.g., [processData.foo == 'bar']).
  3. Create a Process Entity Implement ProcessContextInterface and WorkflowSerializableInterface in a Laravel Eloquent model:

    use PHPMentors\Workflower\Process\ProcessContextInterface;
    use PHPMentors\Workflower\Persistence\WorkflowSerializableInterface;
    use PHPMentors\Workflower\Workflow\Workflow;
    
    class LoanRequest implements ProcessContextInterface, WorkflowSerializableInterface
    {
        protected $workflow;
        protected $serializedWorkflow;
    
        public function getProcessData(): array
        {
            return [
                'amount' => $this->amount,
                'status' => $this->status,
            ];
        }
    
        // Implement WorkflowSerializableInterface methods...
    }
    
  4. Register Workflower in Laravel Add a service provider to bootstrap Workflower:

    // app/Providers/WorkflowerServiceProvider.php
    namespace App\Providers;
    
    use Illuminate\Support\ServiceProvider;
    use PHPMentors\Workflower\Persistence\WorkflowSerializerInterface;
    use PHPMentors\Workflower\Persistence\WorkflowSerializer;
    
    class WorkflowerServiceProvider extends ServiceProvider
    {
        public function register()
        {
            $this->app->singleton(WorkflowSerializerInterface::class, function ($app) {
                return new WorkflowSerializer();
            });
    
            // Register process definitions
            $this->app->bind('workflower.definition_repository', function ($app) {
                $repository = new \PHPMentors\Workflower\Definition\ProcessDefinitionRepository();
                $repository->addFromDirectory(__DIR__.'/../../resources/config/workflower');
                return $repository;
            });
        }
    }
    

    Register the provider in config/app.php.

  5. Start a Process Use the Process facade or service to trigger workflows:

    use PHPMentors\Workflower\Process\Process;
    
    $process = app(Process::class);
    $loanRequest = new LoanRequest(['amount' => 1000]);
    $processInstance = $process->start('LoanRequestProcess', $loanRequest);
    

Implementation Patterns

Workflow Integration Workflow

  1. BPMN Design → Laravel Model

    • Design workflows in BPMN tools (e.g., Camunda, Signavio).
    • Map BPMN elements to Laravel models:
      • Tasks → Eloquent models with ProcessAwareInterface.
      • Gateways → Conditional logic in ProcessContextInterface::getProcessData().
      • Events → Laravel events or observers.
  2. Process-Aware Services Tag Laravel services with phpmentors_workflower.process_aware to link them to workflows:

    # config/services.php
    'workflower.services' => [
        'App\Services\LoanApprovalService' => [
            'workflow' => 'LoanRequestProcess',
            'context' => 'app',
        ],
    ],
    

    Implement ProcessAwareInterface in services:

    class LoanApprovalService implements ProcessAwareInterface
    {
        protected $process;
    
        public function setProcess(Process $process)
        {
            $this->process = $process;
        }
    
        public function approve(LoanRequest $loan)
        {
            $this->process->completeWorkItem($loan);
            // Additional business logic...
        }
    }
    
  3. Workflow Execution Flow

    • Start: Trigger via Laravel events, controllers, or commands.
      event(new LoanRequestSubmitted($loanRequest));
      
    • Complete Tasks: Call completeWorkItem() on the process instance.
      $process->completeWorkItem($loanRequest);
      
    • Handle Gateways: Use ProcessContextInterface::getProcessData() for dynamic routing.
      // In BPMN: [processData.approved == true]
      
  4. Persistence

    • Serialize workflow state to a blob field in Eloquent:
      $loanRequest->setSerializedWorkflow($workflow->serialize());
      $loanRequest->save();
      
    • Deserialize on retrieval:
      $workflow = $loanRequest->getWorkflow();
      
  5. Querying Workflows Use Laravel query scopes to filter processes by activity or status:

    class LoanRequest extends Model
    {
        public function scopePendingApproval($query)
        {
            return $query->where('current_activity', 'approve_task');
        }
    }
    

Common Use Cases

Use Case Implementation Pattern
Approval Workflows Use UserTask in BPMN + ProcessAware services for manual approvals.
Conditional Branching Define ExclusiveGateway in BPMN with expressions like [processData.amount > 1000].
Parallel Tasks Use ParallelGateway in BPMN to split/join workflow paths.
External API Calls Use ServiceTask in BPMN + Laravel HTTP clients to call APIs.
Notifications Trigger Laravel notifications when tasks are assigned (work_item_assigned event).
Retry Mechanisms Implement ProcessListenerInterface to handle failed tasks.

Gotchas and Tips

Pitfalls

  1. Undefined Sequence Flow Evaluation

    • Issue: Conditional branches in ExclusiveGateway may not behave as expected if expressions overlap or are ambiguous.
    • Fix: Test all possible paths manually or use a BPMN validator like BPMN.io.
  2. Serialization Failures

    • Issue: Complex objects in ProcessContextInterface::getProcessData() may not serialize properly.
    • Fix: Use JSON-serializable data or implement __serialize()/__unserialize() in custom objects.
  3. Laravel Service Container Conflicts

    • Issue: Workflower’s DI may clash with Laravel’s container.
    • Fix: Prefer Laravel’s service binding over Workflower’s autowiring:
      $this->app->bind('phpmentors_workflower.process', function ($app) {
          return new Process($app['workflower.definition_repository']);
      });
      
  4. Performance with Large Workflows

    • Issue: Complex BPMN files may slow down process startup.
    • Fix: Cache parsed definitions:
      $repository = new ProcessDefinitionRepository();
      $repository->setCache(new \Symfony\Component\Cache\Simple\FilesystemCache());
      
  5. Missing Workflow Context

    • Issue: Forgetting to configure workflow_contexts in WorkflowerBundle (if used).
    • Fix: Ensure definition_dir points to a valid directory with .bpmn files.

Debugging Tips

  1. Log Workflow State Add a listener to log transitions:

    $process->addListener(new class implements ProcessListenerInterface {
        public function onTransition(Process $process, Transition $transition)
        {
            \Log::info("Transition: {$transition->getSource()->getId()} -> {$transition->getTarget()->getId()}");
        }
    });
    
  2. Inspect Process Data Dump ProcessContextInterface::getProcessData() to verify values:

    \Log::debug('Process Data:', $loanRequest->getProcessData());
    
  3. Validate BPMN Files Use online validators or tools like BPMN.io to check for errors before importing.

  4. Handle Serialization Errors Catch exceptions during deserialization:

    try {
        $workflow = $loanRequest->getWorkflow();
    } catch (\RuntimeException $e) {
        \Log::error("Workflow deserialization failed: " . $e->getMessage());
        $workflow = $loanRequest->getWorkflow()->reset();
    }
    

Extension Points

  1. Custom Serializers Extend WorkflowSerializerInterface for custom storage (e.g., Redis):

    class RedisWorkflowSerializer implements WorkflowSerializerInterface
    {
        public function serialize(Workflow $workflow): string
        {
            return json_encode($workflow->toArray());
        }
    
        public function deserialize(string $serialized): Workflow
        {
            return Workflow::fromArray(json_decode($serialized, true));
        }
    }
    
  2. Custom Process Listeners Implement ProcessListenerInterface to react to workflow events:

    class NotificationListener implements ProcessListenerInterface
    
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
besmartand-pro/php-quality-config
sentix/ai-chatbot
terminal42/code-quality-tools
codifyo/ts-generator-bundle
testo/fiber
mintobit/jobqueue
a4sex/maintenance-bundle
a4sex/entity-date-update
a4sex/client-identifier
a4sex/base-utilites
a4sex/key-value-storage
a4sex/micro-status
chilldev/dependency-injection-extra
datinglibre/datinglibre-app-api
biberltd/corebundle
bricre/symfony-bundle-test
biberltd/logbundle
dominium/http-adapter-bundle
dominium/google-analytics
a4sex/auto-clean-entity