1. Go to this page and download the library: Download chevere/workflow 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/ */
chevere / workflow example snippets
use function Chevere\Workflow\{workflow, sync, variable, run};
// 1. Define a workflow with jobs
$workflow = workflow(
greet: sync(
fn(string $name): string => "Hello, {$name}!",
name: variable('username')
)
);
// 2. Run with variables
$result = run($workflow, username: 'World');
// 3. Get typed responses
echo $result->response('greet')->string();
// Output: Hello, World!
use function Chevere\Workflow\{workflow, sync, async, variable, response, run};
$workflow = workflow(
// Simple calculation
add: sync(
fn(int $a, int $b): int => $a + $b,
a: 10,
b: variable('number')
),
// Format the result
format: sync(
fn(int $sum): string => "Sum: {$sum}",
sum: response('add')
)
);
$result = run($workflow, number: 5);
echo $result->response('format')->string(); // Sum: 15
use Chevere\Action\Action;
class FetchUser extends Action
{
public function __invoke(int $userId): array
{
// Fetch user from database
return ['id' => $userId, 'name' => 'John', 'email' => '[email protected]'];
}
}
class SendEmail extends Action
{
public function __invoke(string $email, string $subject): bool
{
// Send email logic
return true;
}
}
class StringHelper
{
public static function uppercase(string $text): string
{
return strtoupper($text);
}
public function reverse(string $text): string
{
return strrev($text);
}
}
workflow(
first: sync(ActionA::class), // Runs first
second: sync(ActionB::class), // Waits for first
third: sync(ActionC::class), // Waits for second
);
// Graph: first → second → third
if ($result->skip()->contains('optionalJob')) {
// Job was skipped
}
use Chevere\Workflow\Interfaces\WorkflowProviderInterface;
use Chevere\Workflow\Interfaces\WorkflowInterface;
class MyProvider implements WorkflowProviderInterface
{
public static function workflow(): WorkflowInterface
{
return workflow(/* ... */);
}
}
use Chevere\Workflow\WorkflowDiscovery;
$discovery = WorkflowDiscovery::fromDirectory('/path/to/src');
// `workflow()` providers e.g. [OrderWorkflow::class, UserWorkflow::class, ...]
$workflowProviders = $discovery->providers();
// Job action classes e.g. [UserCreate::class, OrderCreate::class, ...]
$workflowDependencies = $discovery->dependencies();
$dependencies = new Dependencies(
...$discovery->dependencies(),
...$discovery->providers()
);
$dependencies->assert($container);
foreach ($discovery->dependencies() as $class) {
if (! $container->has($class)) {
throw new RuntimeException("Missing dependency: {$class}");
}
}
use Chevere\Container\Container; // or any PSR-11 container
use function Chevere\Workflow\run;
// Create container with dependencies
$container = new Container(
logger: new Logger(),
database: new Database()
);
// Run workflow with container
// When using chevere/container it will auto-inject and assert
$result = run($workflow, $container, ...$vars);
use Chevere\Action\Action;
class SendNotification extends Action
{
// Dependencies injected automatically
public function __construct(
private LoggerInterface $logger,
private MailerInterface $mailer
) {}
public function __invoke(string $email, string $message): bool
{
$this->logger->info("Sending email to {$email}");
return $this->mailer->send($email, $message);
}
}
// Provide dependencies in container
$container = new Container(
logger: new ConsoleLogger(),
mailer: new SmtpMailer()
);
$workflow = workflow(
notify: sync(
SendNotification::class, // Dependencies auto-injected
email: variable('userEmail'),
message: 'Welcome!'
)
);
$result = run($workflow, $container, userEmail: '[email protected]');
class ProcessOrder
{
// Dependencies injected automatically
public function __construct(
private DatabaseInterface $database,
private PaymentGateway $payment
) {}
public function __invoke(int $orderId, float $amount): array
{
$order = $this->database->getOrder($orderId);
$result = $this->payment->charge($amount);
return ['order' => $order, 'payment' => $result];
}
}
// Provide dependencies in container
$container = new Container(
database: new MySQLDatabase(),
payment: new StripeGateway()
);
$workflow = workflow(
process: sync(
ProcessOrder::class, // Dependencies auto-injected
orderId: variable('orderId'),
amount: variable('amount')
)
);
$result = run($workflow, $container, orderId: 123, amount: 99.99);
use Chevere\Workflow\Traits\WorkflowProviderTestTrait;
class MyWorkflowProviderTest extends PHPUnit\Framework\TestCase
{
use WorkflowProviderTestTrait;
public function testProviderGraph(): void
{
$this->assertWorkflowGraph(
[['a', 'b'], ['c']],
MyProvider::class
);
}
}
public function testWorkflowResponses(): void
{
$result = run($workflow, input: 'test');
$this->assertSame('expected', $result->response('job1')->string());
$this->assertSame(42, $result->response('job2', 'count')->int());
}
use Chevere\Workflow\Traits\ExpectWorkflowExceptionTrait;
class WorkflowExceptionTest extends TestCase
{
use ExpectWorkflowExceptionTrait;
public function testJobFailure(): void
{
$this->expectWorkflowException(
closure: fn() => run($workflow, input: 'invalid'),
exception: InvalidArgumentException::class,
job: 'validate',
message: 'Invalid input provided'
);
}
}