phpflo/phpflo-bundle
Symfony bundle integrating phpflo/phpflo, the PHP flow-based programming (FBP) library. It helps wire components into dataflow networks inside Symfony apps, letting you define and run modular, event-driven processing pipelines with familiar FBP concepts. Small package with limited adoption, so revie...
First reality check: this is a Symfony bundle, not a Laravel package. It ships a Symfony Bundle class, a DI extension, and YAML config — there is no ServiceProvider, no facade, and no publishable config. Laravel will not auto-discover it. The v1.1.2 release (dependency cleanup only — see below) does nothing to change that. Given 4 stars, 0 dependents, and a package that sat dormant from February 2017 until this maintenance bump, treat the bundle itself as a reference implementation and expect to consume phpflo/phpflo (the core library) directly unless you have a specific reason not to.
Minimal steps if you still want to evaluate it:
composer require phpflo/phpflo — start with the core library, not the bundle.DependencyInjection/ extension class to see what it wires up (typically a Graph/Network factory and a component registry). That's the entire value the bundle adds on top of core.ServiceProvider manually — do not try to instantiate the Symfony bundle.$graph = new \PhpFlo\Graph();
$graph->addNode('reader', 'ReadFile'); // component name from phpflo/phpflo
$graph->addNode('counter', 'CountLines');
$graph->addEdge('reader', 'out', 'counter', 'in');
$network = new \PhpFlo\Network($graph);
$network->run(); // synchronous, blocking
First real use case: a graph-shaped data pipeline — file/stream ingestion, fan-out/fan-in transforms, or multi-stage ETL where Illuminate\Pipeline feels too linear. If your processing is a straight line of steps, stop here and use native Illuminate\Pipeline.
Skip the bundle, wrap the core. The most maintainable Laravel integration is a thin package of your own: composer require phpflo/phpflo, then define a FlowServiceProvider that binds Graph and Network as scoped singletons and registers your custom components in a registry array.
Graph definition lives in code, not YAML. The bundle's YAML component registration is Symfony-specific and won't travel. Define graphs fluently in a dedicated class:
final class SalesReportFlow
{
public function __construct(private ComponentRegistry $registry) {}
public function graph(): Graph
{
$graph = new Graph();
$graph->addNode('source', 'ReadCsv', ['path' => storage_path('app/sales.csv')]);
$graph->addNode('map', 'MapRows');
$graph->addNode('sink', 'WriteJson');
$graph->addEdge('source', 'out', 'map', 'in');
$graph->addEdge('map', 'out', 'sink', 'in');
return $graph;
}
}
Run flows in queue jobs or artisan commands, not in HTTP requests. Network::run() is blocking and synchronous. A RunFlow job per execution keeps web requests fast and gives you retries/backoff for free:
class RunFlow implements ShouldQueue
{
public function handle(NetworkFactory $factory): void
{
$factory->make(SalesReportFlow::class)->run();
}
}
Components as container-resolved services. Register each PhpFlo\Component subclass in a small registry or Laravel container alias mapping 'ReadCsv' => ReadCsvComponent::class. This is the one place where manually copying the Symfony bundle's extension logic is worth the effort — it keeps component construction lazy and injectable.
Two integration styles:
Graph, hand it to Network, run it. Good for batch/CLI pipelines.Testing: build minimal graphs (Source -> Transform -> Sink) and assert on collected output packets rather than asserting on Network internals. Components are plain classes — unit test them independently of the graph.
php-utilities dependency and tidied file headers. That removes one common source of composer require conflicts, so try a normal install on your target PHP 8.x first. If you still hit constraint errors, pin phpflo/phpflo, use --ignore-platform-reqs, or fork — but expect less friction than before this release.Network as a singleton across requests under Octane or in long-lived queue workers — use scoped/bind semantics and rebuild per execution.Network::run() blocks until the graph completes or stalls. A malformed graph with a disconnected out-port can silently deadlock or finish with no output. Always include a timeout/watchdog or a maximum-packet component.addEdge on wrong port names can be quiet. Enable phpflo's logger (Psr\Log compatible) and add a temporary var_dump/log component between nodes to inspect packets.Component subclasses, custom graphs, and the bundle's component-registration config (which you'll reimplement). The .fbp DSL loader exists but is unmaintained — prefer programmatic graphs.phpflo/phpflo if this becomes load-bearing, and keep an exit plan to a maintained dataflow library or hand-rolled Illuminate\Pipeline + jobs.How can I help you explore Laravel packages today?