Weave 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 Bundle Laravel Package

free-agent/workflow-bundle

Free Agent's Workflow Bundle brings structured workflow management to PHP applications. Define multi-step processes, manage transitions, and track state in one lightweight package. A practical choice for projects needing simple, configurable workflow orchestration.

View on GitHub
Deep Wiki
Context7

Getting Started

Reality check first: free-agent/workflow-bundle is a Symfony2 bundle, not a Laravel package. It is archived (2 stars, 0 dependents), so there is no path where you composer require it into a Laravel app and get a working service provider. Treat this assessment as "how would I use this if I inherited a Symfony 2.x codebase" plus "what would I actually do in Laravel instead."

If you are in the legacy Symfony app it was written for:

  1. composer require free-agent/workflow-bundle — expect PHP 5.6/7.x-era constraints; check composer.json before assuming it installs on modern PHP.
  2. Register the bundle in app/AppKernel.php (new FreeAgent\WorkflowBundle\FreeAgentWorkflowBundle()). There is no auto-discovery; Symfony2 bundles are wired explicitly.
  3. Look first at, in this order: README.md (the config tree and any example YAML), DependencyInjection/Configuration.php (the authoritative schema for defining workflows), the main workflow/registry service class, and the interface your entity must implement to be a workflow subject. The tests are the best documentation for guard/callback semantics.
  4. Configure one workflow in config.yml for a single entity with a small state set — draft → submitted → approved — and one transition. Call the workflow service from a controller, persist the entity, and assert the state changed and that an invalid transition throws.

What a Laravel developer should actually do: install symfony/workflow (the standalone, maintained component — this bundle is essentially a predecessor of it) or hand-roll an enum + a transition service. The bundle's ideas port cleanly; its code does not.

Implementation Patterns

Declarative definitions beat inline if chains. The bundle's model is a named workflow containing places (states) and transitions, defined in config rather than scattered across controllers. In Laravel, mirror this with a config array or a WorkflowDefinition value object registered per model class:

// config/workflows.php
Order::class => [
    'places' => ['draft', 'submitted', 'approved', 'rejected'],
    'transitions' => [
        'submit'  => ['from' => ['draft'], 'to' => 'submitted'],
        'approve' => ['from' => ['submitted'], 'to' => 'approved'],
        'reject'  => ['from' => ['submitted'], 'to' => 'rejected'],
    ],
],

Subject interface on the model. The bundle expects your entity to expose a state property and implement a marker interface. In Laravel that becomes a HasWorkflow trait on the Eloquent model with a workflowState() accessor reading a state column.

Thin controllers, fat transition service. The bundle's service is a registry/dispatcher; don't call it from Blade or from five places in a controller. Wrap it:

class TransitionOrder
{
    public function __construct(private WorkflowManager $wf) {}

    public function handle(Order $order, string $transition): void
    {
        DB::transaction(function () use ($order, $transition) {
            $order = Order::whereKey($order->id)->lockForUpdate()->firstOrFail();
            $this->wf->apply($order, $transition); // guards run here
            $order->save();
            event(new OrderTransitioned($order, $transition));
        });
    }
}

Guards for preconditions, events for side effects. The bundle separates guards (may this transition happen?) from callbacks/hooks (what runs after?). Keep it that way: guards should be pure predicates that throw a domain exception; emails, audit rows, and notifications belong in listeners fired after the transition succeeds. Side effects inside a guard are the fastest way to get a half-applied transition when something downstream fails.

Expose allowed transitions to the UI. Call the workflow to list legal transitions for the current state and render buttons from that list. This is the single highest-value day-to-day use — it eliminates the "button that 500s" class of bug.

Test the transition matrix, not the happy path. A data provider asserting every (state, transition) pair is allowed or rejected catches ~90% of workflow regressions and takes twenty minutes to write.

Gotchas and Tips

  • Archived means frozen. No security patches, no PHP 8 fixes, no compatibility with modern Symfony. Any use is a liability; if it's already in production, budget for replacement with symfony/workflow, which is framework-agnostic and maintained.
  • Symfony2 bundle ≠ Laravel package. No service provider, no facade, no auto-discovery, and the DI wiring is XML/YAML container config. There is no reasonable adapter path — the container contracts don't exist in Laravel.
  • State is almost certainly a free-form string column. No DB-level enum or check constraint, so typos in config silently create unreachable states. Add validation at the model layer or a CHECK constraint.
  • No concurrency control by default. Two simultaneous requests can both pass the guard and both write. Always wrap in a transaction with lockForUpdate() (or an optimistic version column) before applying a transition.
  • Guard failures vs. bugs look identical. A guard that throws InvalidTransitionException and a guard that throws TypeError both surface as 500s unless you catch and distinguish. Log every transition attempt with actor, from-state, to-state, and outcome.
  • Don't treat the current-state column as history. The bundle tracks state, not an audit trail. Add an append-only transitions table if anyone will ever ask "who approved this and when."
  • Config changes are code changes. Adding a state or transition requires a deploy; plan for that rather than expecting ops to tweak workflow at runtime.
  • Extension points to look for (useful even as a design reference): custom guard classes registered in the container, and an event dispatcher hook for post-transition callbacks. Those two hooks are the whole extensibility surface; if you need more, you're fighting the package.
  • For greenfield Laravel work, skip it entirely. symfony/workflow via Composer, or a ~150-line enum + transition service, gives you the same model with maintained dependencies and no Symfony2 baggage.
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.
coleus/frame
thtg88/journalism
filagora/filagora-ai-forums
rlacerda83/query-parser
socialdept/atp-orm
cboxdk/laravel-assistant-client
socialdept/atp-resolver
socialdept/tenant-domains
tautvydasr/blade-class-names
socialdept/color-scales
maherelgamil/controller
coleus/widgets
coleus/table
coleus/users
coleus/music
coleus/health
coleus/calendar
coleus/notes
coleus/support
coleus/settings