PHP code example of particle-academy / fancy-flow-php
1. Go to this page and download the library: Download particle-academy/fancy-flow-php library. Choose the download type require.
2. Extract the ZIP file and open the index.php.
3. Add this code to the index.php.
<?php
require_once('vendor/autoload.php');
/* Start to develop here. Best regards https://php-download.com/ */
particle-academy / fancy-flow-php example snippets
use FancyFlow\Workflow;
use FancyFlow\NodeKindRegistry;
use FancyFlow\Registry\Builtin;
use FancyFlow\Engine\FlowRunner;
use FancyFlow\Runtime\RunOptions;
// 1. Register the built-in node kinds (or your own) so import can validate.
$registry = Builtin::register(new NodeKindRegistry());
// 2. Import a WorkflowSchema exported from <FlowEditor> (JSON string or array).
$import = Workflow::import($json, registry: $registry); // -> ImportResult { ok, graph, issues[] }
// 3. Run it. Builtin::executors() ships batteries-
use FancyFlow\Capabilities\{Capabilities, LlmClient, LlmRouteRequest, LlmRouteChoice};
final class MyRouter implements LlmClient
{
public function chooseRoute(LlmRouteRequest $request): LlmRouteChoice
{
// $request->prompt, $request->routes, $request->ports(), …
return new LlmRouteChoice(port: 'billing', reason: 'duplicate charge');
}
}
Capabilities::setLlmClient(new MyRouter()); // or bind LlmClient in the container
use FancyFlow\Capabilities\{Capabilities, WorkflowResolver};
final class FileResolver implements WorkflowResolver
{
public function resolve(string $ref): ?FlowGraph
{
return Workflow::import(json_decode(file_get_contents("flows/{$ref}.json"), true))->graph;
}
}
Capabilities::setWorkflowResolver(new FileResolver());
// 1. Kind — shape + validation, shared with the editor.
$registry->register(NodeKind::fromArray([
'name' => 'geocode', 'category' => 'io', 'label' => 'Geocode',
'configSchema' => [['type' => 'text', 'key' => 'address', 'label' => 'Address', 'e('node-7', SpecialExecutor::class); // by node id (highest precedence)
use FancyFlow\Laravel\Facades\FancyFlow;
$result = FancyFlow::run($schema, ['trigger-1' => ['payload' => $request->all()]]);
// A custom node with full DI (kind + executor in one call):
FancyFlow::extend('geocode', GeocodeExecutor::class, [
'name' => 'geocode', 'category' => 'io', 'label' => 'Geocode',
]);
// …or co-locate both with the attribute + `php artisan flow:discover`:
#[FlowNode('geocode', category: 'io', label: 'Geocode')]
final class GeocodeExecutor implements NodeExecutor { /* ... */ }
Route::flow('/hooks/onboard', $schema); // POST → dispatch a durable run
class Project extends Model { use HasWorkflows; } // $project->workflows()
// config/fancy-flow.php -- up to 4 of a run's nodes at once, or "unlimited" (or 0)
'queue' => ['max_concurrent' => 4],
// one run, while the host stays serial
FancyFlow::dispatch($schema, $inputs, maxConcurrent: DispatchLimit::UNLIMITED);
use FancyFlow\Testing\QueuePump;
Queue::fake();
QueuePump::reset(); // per test -- the cursor is static
FancyFlow::dispatch($schema);
QueuePump::drain(); // run it out
QueuePump::drain(maxNodes: 2); // ...or kill the worker after two nodes
FancyFlow::dispatchCohort(
[$enrichFlow, $archiveFlow, $notifyFlow], // declared order IS the run order
['trigger' => $deal->toArray()], // snapshotted per run at dispatch
guard: ['name' => 'record-exists', 'args' => ['model' => Deal::class, 'id' => $deal->id]],
);
$notify->status; // 'skipped'
$notify->skipped_reason; // 'App\Models\Deal 41 no longer exists'