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

Workflow Laravel Package

cvek/workflow

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation Add the package via Composer:

    composer require cvek/workflow
    

    For Laravel (Symfony-based), ensure compatibility with Symfony components (e.g., symfony/workflow).

  2. First Use Case: Basic Workflow Definition Define a workflow in a Laravel service provider or config file:

    use Cvek\Workflow\Workflow;
    
    $workflow = new Workflow('order_workflow', [
        'draft' => ['allowed_to' => ['submit']],
        'submitted' => ['allowed_to' => ['approve', 'reject']],
        'approved' => ['allowed_to' => []],
        'rejected' => ['allowed_to' => []],
    ]);
    
  3. Register Workflow Bind the workflow to Laravel’s container in a service provider:

    $this->app->singleton('order_workflow', fn() => $workflow);
    
  4. Apply to a Model Use the HasWorkflow trait on a model (e.g., Order):

    use Cvek\Workflow\Traits\HasWorkflow;
    
    class Order extends Model
    {
        use HasWorkflow;
    
        protected $workflowKey = 'order_workflow';
    }
    
  5. Trigger a Transition Transition an order state in a controller or command:

    $order = Order::find(1);
    $order->apply('submit'); // Transitions from 'draft' to 'submitted'
    

Implementation Patterns

Workflow Integration with Eloquent

  1. State Persistence Store the current state in a database column (e.g., status):

    protected $workflowStateColumn = 'status';
    
  2. Validation Before Transition Override canApply() to add custom logic:

    public function canApply($transition)
    {
        if ($transition === 'approve' && $this->amount > 1000) {
            return false;
        }
        return parent::canApply($transition);
    }
    
  3. Event Listeners Attach workflow events (e.g., transitioning, transitioned) via Laravel’s event system:

    $order->onTransitioning(fn($transition) => Log::info("Transitioning to $transition"));
    

Workflow in API/CLI

  1. API Endpoints Create a controller to handle transitions:

    public function transition(Order $order, $transition)
    {
        if ($order->canApply($transition)) {
            $order->apply($transition);
            return response()->json(['success' => true]);
        }
        return response()->json(['error' => 'Invalid transition'], 400);
    }
    
  2. Artisan Commands Build a command for bulk transitions:

    public function handle()
    {
        Order::where('status', 'draft')->each(fn($order) => $order->apply('submit'));
    }
    

Advanced: Custom Workflows

  1. Dynamic Workflows Load workflows from a database or config:

    $workflow = new Workflow('dynamic_workflow', config('workflows.dynamic'));
    
  2. Guard Clauses Extend the WorkflowGuard trait to enforce rules:

    class CustomGuard extends WorkflowGuard
    {
        public function canApply($transition, $object)
        {
            if ($object->isAdmin() && $transition === 'force_approve') {
                return true;
            }
            return parent::canApply($transition, $object);
        }
    }
    

Gotchas and Tips

Pitfalls

  1. State Initialization Ensure the model’s initial state matches the workflow’s starting place (e.g., draft). Use boot() to set defaults:

    protected static function boot()
    {
        parent::boot();
        static::creating(fn($model) => $model->status = 'draft');
    }
    
  2. Circular Dependencies Avoid recursive transitions (e.g., A → B → A). Validate transitions explicitly:

    if ($order->status === 'approved' && $transition === 'reject') {
        throw new \RuntimeException('Cannot reject an approved order.');
    }
    
  3. Race Conditions Use database transactions for critical transitions:

    DB::transaction(fn() => $order->apply('submit'));
    

Debugging

  1. Log Transitions Enable debug mode in the workflow:

    $workflow->setDebug(true); // Logs transitions to Laravel logs.
    
  2. Check Allowed Transitions Use getAllowedTransitions() to inspect valid moves:

    dd($order->getAllowedTransitions()); // ['submit']
    

Extension Points

  1. Custom Transition Logic Override apply() to add pre/post hooks:

    public function apply($transition)
    {
        $this->fireTransitioning($transition);
        $this->updateState($transition);
        $this->fireTransitioned($transition);
    }
    
  2. Workflow Events Listen for transitions globally:

    event(new OrderTransitioning($order, 'submit'));
    
  3. Testing Mock workflows in tests:

    $workflow = Mockery::mock(Workflow::class);
    $workflow->shouldReceive('canApply')->andReturn(true);
    $order->setWorkflow($workflow);
    
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.
hamzi/corewatch
minionfactory/raw-hydrator
hexters/coinpayment
rjcodes/rjcms
act-training/laravel-permissions-manager
alimarchal/laravel-chart-of-accounts
babenkoivan/elastic-scout-driver
mkwebdesign/filament-watchdog-v5
renatomarinho/laravel-page-speed
zedmagdy/filament-business-hours
renatovdemoura/blade-elements-ui
devgeek/beacon-admin
benjamin-rqt/data-watcher-bundle
atriumphp/atrium
sandermuller/package-boost-laravel
sandermuller/boost-skills
redaxo/core
yusufgenc/filament-api-forge
l3aro/rating-star-for-filament
leek/filament-subtenant-scope