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

symfony/workflow

Symfony Workflow component helps model and run workflows or finite state machines. Define places and transitions, guard rules, events, and marking stores to track state changes and integrate processes cleanly into your application.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Steps to First Use Case

  1. Install the Package

    composer require symfony/workflow
    

    For Laravel, prefer using Symfony’s standalone component (no framework bundle needed).

  2. Define a Workflow (YAML/Array) Create a workflow definition (e.g., config/workflows/order_workflow.yaml):

    # Example: Order Processing Workflow
    order_workflow:
      support:
        - 'Symfony\Component\Workflow\WorkflowInterface'
        - 'Symfony\Component\Workflow\MarkingStoreInterface'
      marking_store:
        type: 'method'
        property: 'status'
        getter: 'getStatus'
        setter: 'setStatus'
      initial_marking: 'draft'
      places:
        - name: 'draft'
        - name: 'submitted'
        - name: 'approved'
        - name: 'rejected'
        - name: 'shipped'
        - name: 'delivered'
      transitions:
        submit:
          from: 'draft'
          to: 'submitted'
        approve:
          from: 'submitted'
          to: 'approved'
        reject:
          from: 'submitted'
          to: 'rejected'
        ship:
          from: 'approved'
          to: 'shipped'
        deliver:
          from: 'shipped'
          to: 'delivered'
    
  3. Load the Workflow in Laravel Use a service provider or manually instantiate:

    use Symfony\Component\Workflow\Workflow;
    use Symfony\Component\Workflow\MarkingStore\MethodMarkingStore;
    use Symfony\Component\Workflow\Support\YamlWorkflowDefinition;
    
    // In a service provider or bootstrap file
    $definition = new YamlWorkflowDefinition(file_get_contents(__DIR__.'/config/workflows/order_workflow.yaml'));
    $workflow = new Workflow($definition);
    $markingStore = new MethodMarkingStore($order, 'status', 'getStatus', 'setStatus');
    $workflow->apply($markingStore);
    
  4. Apply Transitions in Code

    // Transition an order from 'draft' to 'submitted'
    $workflow->apply($order, 'submit');
    
    // Check current state
    if ($workflow->can($order, 'approve')) {
        $workflow->apply($order, 'approve');
    }
    
  5. First Use Case: Order Status UI Display allowed transitions in a Blade view:

    @foreach ($workflow->getEnabledTransitions($order) as $transition)
        <button onclick="applyTransition('{{ $transition->getName() }}')">
            {{ ucfirst($transition->getName()) }}
        </button>
    @endforeach
    

Where to Look First


First Practical Example: User Account Activation

  1. Define Workflow (config/workflows/user_activation.yaml):
    user_activation:
      initial_marking: 'pending'
      places:
        - name: 'pending'
        - name: 'activated'
        - name: 'suspended'
        - name: 'banned'
      transitions:
        activate:
          from: 'pending'
          to: 'activated'
        suspend:
          from: ['activated', 'pending']
          to: 'suspended'
        ban:
          from: ['activated', 'pending', 'suspended']
          to: 'banned'
    
  2. Apply in User Model:
    use Symfony\Component\Workflow\Workflow;
    
    class User extends Model
    {
        protected $workflow;
    
        public function boot()
        {
            $definition = new YamlWorkflowDefinition(file_get_contents(__DIR__.'/../../config/workflows/user_activation.yaml'));
            $this->workflow = new Workflow($definition);
            $this->workflow->apply($this);
        }
    
        public function activate()
        {
            $this->workflow->apply($this, 'activate');
            $this->save();
        }
    }
    
  3. Use in Controller:
    public function activate(User $user)
    {
        $user->activate();
        return redirect()->route('dashboard');
    }
    

Implementation Patterns

1. Workflow Definition Patterns

YAML vs. Array Definitions

  • YAML: Best for complex workflows (e.g., multi-step approvals) or team collaboration.
    # config/workflows/hr_onboarding.yaml
    hr_onboarding:
      initial_marking: 'submitted'
      places:
        - name: 'submitted'
          transitions: ['review', 'reject']
        - name: 'under_review'
          transitions: ['approve', 'request_changes']
        - name: 'approved'
          transitions: ['hire']
        - name: 'rejected'
        - name: 'on_hold'
      transitions:
        review:
          from: 'submitted'
          to: 'under_review'
        approve:
          from: 'under_review'
          to: 'approved'
        reject:
          from: ['submitted', 'under_review']
          to: 'rejected'
        request_changes:
          from: 'under_review'
          to: 'submitted'
        hire:
          from: 'approved'
          to: 'hired'
    
  • Array: Best for dynamic or code-generated workflows (e.g., tenant-specific rules).
    $definition = [
        'initial_marking' => 'draft',
        'places' => [
            ['name' => 'draft'],
            ['name' => 'published'],
            ['name' => 'archived'],
        ],
        'transitions' => [
            'publish' => ['from' => 'draft', 'to' => 'published'],
            'archive' => ['from' => 'published', 'to' => 'archived'],
        ],
    ];
    $workflow = new Workflow(new ArrayWorkflowDefinition($definition));
    

Dynamic Workflows

Use workflow factories for tenant-specific or role-based workflows:

class WorkflowFactory
{
    public static function createForTenant(Tenant $tenant)
    {
        $definition = self::getDefinitionForTenant($tenant);
        return new Workflow(new ArrayWorkflowDefinition($definition));
    }

    protected static function getDefinitionForTenant(Tenant $tenant): array
    {
        return match ($tenant->plan) {
            'enterprise' => self::enterpriseWorkflow(),
            default => self::standardWorkflow(),
        };
    }
}

2. Marking Store Patterns

Method Marking Store (Simple Models)

$markingStore = new MethodMarkingStore(
    $order,          // Subject
    'status',        // Property name
    'getStatus',     // Getter method
    'setStatus'      // Setter method
);
$workflow->apply($markingStore);
  • Pros: Zero database changes, works with any Eloquent model.
  • Cons: Not ideal for high-frequency updates (e.g., 1000+ transitions/sec).

Doctrine Marking Store (Database-Backed)

use Symfony\Component\Workflow\MarkingStore\DoctrineMarkingStore;

$markingStore = new DoctrineMarkingStore(
    $entityManager,
    $order,          // Subject
    'order_status'   // Table name
);
$workflow->apply($markingStore);
  • Pros: Persistent across requests, scalable for high traffic.
  • Cons: Requires Doctrine (or custom DB store for Laravel Query Builder).

Custom Marking Store (Advanced)

use Symfony\Component\Workflow\MarkingStore\MarkingStoreInterface;

class RedisMarkingStore implements MarkingStoreInterface
{
    public function __construct(private Redis $redis) {}

    public function getMarking(string $name): ?string
    {
        return $this->redis->get("workflow:{$name}");
    }

    public function setMarking(string $name, ?string $marking): void
    {
        $this->redis->set("workflow:{$name}", $marking);
    }

    public function getMarkings(): array
    {
        return [$this->getMarking('status')];
    }
}
  • Use Case: Distributed systems (e.g., Laravel + Horizon) or caching workflow states.

3. Guard Conditions

Add logic to transitions (e.g., "only approve if budget > $X"):

transitions:
  approve:
    from: 'submitted'
    to: 'approved'
    guard: 'order_budget_guard'
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