sprintf/wolfflow-bundle
sprintf/wolfflow-bundle is a Symfony bundle that integrates WolfFlow workflow capabilities into PHP applications. It provides configuration, service container wiring, and workflow definitions to help developers model, execute, and monitor business processes with less boilerplate and cleaner Symfony...
The first thing to internalize: this is a Symfony bundle, not a Laravel package. composer require sprintf/wolfflow-bundle in a Laravel app will drop code into vendor/, but nothing boots — there is no ServiceProvider, no mergeConfigFrom, no facade, and php artisan vendor:publish will not find it. The bundle's entry point is a Bundle subclass registered in Symfony's config/bundles.php, with all wiring done through a DependencyInjection\*Extension and tagged services.
So for a Laravel developer there are three realistic paths, in order of effort:
composer show and look at vendor/sprintf/wolfflow-bundle/composer.json — the require block tells you which core package to depend on instead. That core is what you actually want in Laravel.symfony/workflow standalone or a Laravel-native state machine instead.The docs are almost certainly thin (5 stars, 0 dependents), so read source in this order:
README.md — usually the only prose documentation.src/DependencyInjection/Configuration.php — the real config schema. This is your source of truth for every option; treat it as the manual.src/DependencyInjection/WolfflowExtension.php — what services and tags get registered, and how workflows are collected.src/Resources/config/*.xml|yaml — service definitions and tag names, which reveal the extension seams.src/EventSubscriber/ (or src/Listener/) — lifecycle hooks you'll want to bridge to Laravel events.composer.json and src/ — the reusable part.In Symfony (or as the shape you'll reproduce in Laravel):
# config/packages/wolfflow.yaml
wolfflow:
workflows:
article_approval:
marking_store:
type: single_state
property: status
places: [draft, review, approved, rejected]
transitions:
submit: { from: draft, to: review }
approve: { from: review, to: approved }
reject: { from: review, to: rejected }
$workflow = $this->workflowRegistry->get($article, 'article_approval');
if ($workflow->can($article, 'approve')) {
$workflow->apply($article, 'approve');
}
In Laravel the equivalent first step is: depend on the core package, define App\Workflows\ArticleApproval with its builder API, bind a registry as a singleton in AppServiceProvider, and apply transitions from an Action class. Persist the marking yourself as a status column cast to a PHP enum — do not try to reuse the bundle's Doctrine marking store against Eloquent.
Pattern A — Core-only in Laravel (recommended). Require the core engine, skip the bundle entirely. Bind a WorkflowRegistry singleton, define workflows in PHP (autoloadable, testable, no config cache surprises), and map the marking to an Eloquent column:
// app/Providers/WorkflowServiceProvider.php
public function register(): void
{
$this->app->singleton(WorkflowRegistry::class, function ($app) {
$registry = new WorkflowRegistry();
foreach (config('workflows') as $name => $definition) {
$registry->add($name, WorkflowBuilder::fromArray($definition)->build());
}
return $registry;
});
}
Pattern B — Port the bundle. Copy the Configuration.php schema into config/wolfflow.php, write a service provider that loops the definitions and constructs workflows, and replace Symfony's compiler pass with $this->app->tagged('wolfflow.workflow') inside register(). Bridge events by subscribing to whatever the core dispatches and re-emitting via event() so the rest of your app hears Laravel-shaped events.
Pattern C — Benchmark against alternatives. If the only need is "state machine on an Eloquent model," symfony/workflow runs standalone with no framework coupling, and there are Laravel-native packages with far more adoption. The Wolfflow bundle then contributes only config/design inspiration.
Domain integration. Keep can() checks in FormRequests or policies and apply() inside Action classes, so the workflow engine never leaks into controllers. Write an append-only workflow_transitions audit table fed by a transition listener. Keep business authorization ("only the editor-in-chief may approve") in your own guards/policies rather than in transition config, unless you've verified the bundle's guard support is substantive.
Testing. Assert on the resulting place after apply(), and write one explicit test that pins down what happens on an illegal transition (exception vs. silent no-op). Do not assume; check once and document it.
Sprint-F/wolfflow-bundle but the Packagist name is sprintf/wolfflow-bundle. Before writing any use statements, run composer show sprintf/wolfflow-bundle and read the autoload PSR-4 prefix — don't guess the namespace.bin/console cache:clear. In a ported Laravel version, php artisan config:cache will freeze your definitions — keep them in code, not cached config, if you plan to deploy with config caching.review and both apply approve. Workflow libraries typically do not solve this. Wrap apply() in a transaction with lockForUpdate() on the model row, or add an optimistic-locking version column.can() until you've confirmed.debug:container --tag=<tag> plus dumping the compiled workflow graph shows the real places/transitions after config merging. In a port, add an artisan wolfflow:debug {workflow} command that prints the graph — it pays for itself the first time a typo in a from place silently makes a transition unreachable.src/: a marking-store interface, a guard/validator interface, and the compiler pass that collects tagged workflows. Those three are the seams you'll need when porting or extending.symfony/workflow (standalone, no framework required), zerodahero/laravel-workflow, brexis/laravel-workflow. For a Laravel codebase you will likely get more value from any of these than from a 5-star Symfony bundle with zero dependents.How can I help you explore Laravel packages today?