Download the PHP package chevere/workflow without Composer
On this page you can find all versions of the php package chevere/workflow. It is possible to download/install these versions without Composer. Possible dependencies are resolved automatically.
Download chevere/workflow
More information about chevere/workflow
Files in chevere/workflow
Package workflow
Short Description Declarative workflow engine for PHP with automatic dependency resolution, sync/async job execution, and type-safe response chaining.
License Apache-2.0
Homepage https://chevere.org
Informations about the package workflow
Workflow
Summary
Chevere Workflow is a PHP library for building and executing multi-step procedures with automatic dependency resolution. Define independent jobs that can run synchronously or asynchronously, pass data between them using typed responses, and let the engine handle execution order automatically.
Key features:
- Declarative job definitions: Define what to do, not how to orchestrate it
- Automatic dependency graph: Jobs execute in optimal order based on their dependencies
- Sync and async execution: Mix blocking and non-blocking jobs freely
- Type-safe responses: Access job outputs with full type safety
- Conditional execution: Run jobs based on variables or previous responses
- Built-in retry policies: Handle transient failures automatically
- Testable: Each job is independently testable and workflow graph can be verified
You define jobs and how they connect and depend on each other, Chevere Workflow figures out the execution order and runs them accordingly.
Integrations
- VS Code Extension: Complete language server support plus graph visualization
- Laravel Integration: Package for integrating with Laravel applications
Installing
Workflow is available through Packagist and the repository source is at chevere/workflow.
Quick Start
Here's a minimal example to get you started:
Core Concepts
Workflow is built around four main concepts:
| Concept | Description |
|---|---|
| Job | A unit of work that produces a response |
| Variable | External input provided when running the workflow |
| Response | Reference to output from a previous job |
| Graph | Automatic execution order based on job dependencies |
How It Works
- You define jobs using
sync()orasync()functions - Jobs declare their inputs: literal values,
variable()references, orresponse()from other jobs - The engine builds a dependency graph automatically
- Jobs execute in optimal order (parallel when possible)
- Access typed responses after execution
Functions Reference
| Function | Purpose |
|---|---|
workflow() |
Create a workflow from named jobs |
sync() |
Create a synchronous (blocking) job |
async() |
Create an asynchronous (non-blocking) job |
variable() |
Declare a runtime variable |
response() |
Reference another job's output |
run() |
Execute a workflow with variables |
Jobs
Jobs are the building blocks of a workflow. Each job wraps an executable unit (Action, Closure, Invocable class, or any PHP callable) and declares its input arguments.
Creating Jobs with Closures
Use closures for simple, inline operations:
Creating Jobs with Action Classes
For complex or reusable logic, use Action classes as these additionally support method definitions for acceptParameters() and acceptReturn() to define parameter and return rules that are automatically applied at runtime.
Creating Jobs with Invocable Classes
Use invocable classes (classes with __invoke method) for reusable logic without needing Action base class:
Creating Jobs with Callables
Use any PHP callable including array callbacks, function names, or static methods:
Sync vs Async Jobs
Synchronous jobs (sync) block execution until complete. Use for operations that must run in sequence:
Asynchronous jobs (async) run concurrently when they have no dependencies:
Job Arguments
Jobs accept three types of arguments:
Jobs can define I/O rules via chevere/parameter. Workflow derives parameter and return definitions from the callable signature or Action reflection and validates inputs and responses at runtime.
Integration with Chevere
Workflow works seamlessly with the chevere/parameter and chevere/action packages. When you declare parameter rules with chevere/parameter (types, ranges, or custom validators), those rules travel with the job definitions and are applied automatically at runtime. Workflow performs the validation layer for you before invoking jobs so callers don't need to repeat input or response checks. The same integration applies to chevere/action Action classes: parameter and return definitions are derived from action signatures and validated by Workflow.
These integrations are optional extras. You do not have to use chevere/parameter or chevere/action to use Workflow, but opting in gives stronger guarantees and reduces validation boilerplate across jobs.
Variables
Variables are placeholders for values provided at runtime. Declare them with variable():
All declared variables must be provided when running the workflow.
Responses
Use response() to pass output from one job to another. This automatically establishes a dependency.
Accessing Nested Response Keys/Properties
When a job returns array or object, access specific keys/properties directly in response():
Execution Graph
The workflow engine automatically builds an execution graph based on job dependencies. Jobs without dependencies run in parallel (when using async), while dependent jobs wait for their dependencies.
Mermaid Graphs
Workflow's graph can be rendered as a Mermaid flowchart for visualization. Each job is a node, and edges represent dependencies. Job conditions are annotated on the node labels.
Generate a Mermaid flowchart using Mermaid::generate():
Where:
- if res(ja)
Job
jbruns only if jobjaresponse is truthy - ifNot var(var)
Job
jbruns only ifvarvariable is not falsy - j1->id @ j2(n:)
Job
j1response key/propertyidis used as argumentnfor jobj2 - j1->name @ j2(m:)
Job
j1response key/propertynameis used as argumentmfor jobj2 - jb @ j3(a:)
Job
jbresponse is used as argumentafor jobj3 - j2 @ j4(i:)
Job
j2response is used as argumentifor jobj4 - j3 @ j4(j:)
Job
j3response is used as argumentjfor jobj4
Running Workflows
Execute a workflow with the run() function:
Accessing Responses
The run result provides type-safe access to job responses:
Check Skipped Jobs
When using conditional execution, check which jobs were skipped:
Workflow Provider Convention
Implement WorkflowProviderInterface to expose a workflow definition from a class:
This is the recommended pattern for packages and applications. It separates workflow configuration from execution logic and enables discovery by tooling such as the Chevere Workflow VSCode extension.
Workflow Discovery
WorkflowDiscovery provides a list for classes implementing WorkflowProviderInterface under providers(), and a list of all class-string dependencies (jobs) under dependencies().
Creating WorkflowDiscovery
Create a discovery instance by providing the path to the directory containing your workflow providers:
Build WorkflowDiscovery
Call build() to persist the discovery results as PHP return files, which you can commit to your repository or load at runtime for faster access without needing to scan directories:
Two files are written:
| File | Contents |
|---|---|
workflow-providers.php |
array<class-string<WorkflowProviderInterface>> providers |
workflow-dependencies.php |
array<class-string> required by discovered job actions |
Call fromBuild() to load the discovery results from the cache files:
Validating Dependencies
To validate that your container can satisfy all discovered dependencies before running any workflow, call assert() on Dependencies with your container instance. It will throw if any required class is missing:
You can also manually check the list of dependencies against your PSR-11 container:
Dependency Injection
Workflow supports automatic dependency injection for any class passed as a class-string using any PSR-11 compatible container. When your jobs reference classes with constructor dependencies, you can provide a container that will automatically resolve and inject those dependencies. chevere/container is one example, but any PSR-11 container works.
Passing a Container
Pass a ContainerInterface instance as the second argument to run():
When a job references a class-string (Action class, invokable class, or any other class), Workflow uses the container to:
- Inject dependencies - Automatically resolve constructor parameters from the container
- Validate availability - Ensure all required dependencies are present before execution
- Support nested dependencies - Recursively resolve dependencies of dependencies
Note: Dependency injection only works for classes passed as class-strings (e.g., MyClass::class). It does not work for closures, already instantiated objects, or array callbacks.
Example with Action Dependencies
Example with Invokable Class Dependencies
Dependency injection also works with invokable classes and any other class:
Conditional Execution
Control whether a job runs using withRunIf() (run when conditions are met) or withRunIfNot() (skip when conditions are met). Both methods accept the same kinds of conditions and are evaluated at run-time.
Accepted condition types
boolean|int|float|stringliteral scalar valuevariable('name')runtime argument coerced to truly/falsyresponse('job')orresponse('job', 'key')uses another job's outputcallableinvokes a callable passing the currentRunInterfacecontext argument
Note: Empty string is considered falsy. To learn more check PHP type comparison tables.
Explicit Dependencies
While response() creates implicit dependencies, use withDepends() for explicit control:
For the code above, cleanup happens only if update runs and completes successfully. If update is skipped (because exists is false), then cleanup is also skipped since it depends on update.
Run After Job
Use withAfter() to enforce ordering between jobs without creating a dependency. It guarantees that the target job is scheduled only after the specified job node has resolved.
For the code above, cleanup happens after node update regardless of whether update actually ran or was skipped.
Without withAfter('update'), cleanup and update are independent and may run in any order (for example, cleanup could run before update). Adding withAfter('update') ensures cleanup is scheduled only after the update node resolves.
Retry Policy
Configure automatic retries for jobs that may fail transiently:
| Parameter | Type | Default | Description |
|---|---|---|---|
timeout |
int<0, max> |
0 |
Max execution time in seconds (0 = unlimited) |
maxAttempts |
int<1, max> |
1 |
Total attempts including initial |
delay |
int<0, max> |
0 |
Seconds between retries (0 = immediate) |
Retry delays use non-blocking sleep, making them safe for async runtimes.
Exception Handling
When a job fails, a WorkflowException wraps the original exception:
Return Early
Throw EarlyReturnException inside a job to stop workflow execution immediately without treating it as an error. Catch it at the call site to handle the early exit gracefully:
Using WorkflowTrait
For class-based workflow management, use WorkflowTrait:
Lint Mode
Set the CHEVERE_WORKFLOW_LINT_ENABLE=1 environment variable to enable lint mode. In this mode both Workflow and Job collect parameter violations instead of throwing on errors, and generate a Mermaid graph on construction.
Call $workflow->lint() to get a JSON report with violations and the Mermaid diagram:
Lint mode is intended for development and CI pipelines to inspect workflow definitions without halting on the first error.
The output conforms to the schema/workflow-lint.schema.json, which you can use to validate lint reports or integrate with tooling.
Testing
Testing Actions
Test your Action classes independently:
Testing Workflow Graph
Verify execution order:
Testing Workflow Providers with PHPUnit
Use Chevere\Workflow\Traits\WorkflowProviderTestTrait in PHPUnit test cases to assert provider correctness:
| Method | Description |
|---|---|
assertWorkflowProvider($provider) |
Asserts the class implements WorkflowProviderInterface |
assertWorkflowGraph($expected, $workflow) |
Asserts the workflow jobs dependency graph matches $expected |
When passing a class string to assertWorkflowGraph, it also calls assertWorkflowProvider internally.
Testing Responses
Test complete workflow execution:
Testing Exceptions
Use ExpectWorkflowExceptionTrait for error scenarios:
Real-World Examples
Image Processing Pipeline
User Registration Flow
Conditional Processing
Demo
Run the included examples:
See the demo directory for all examples.
Documentation
Documentation is available at chevere.org/packages/workflow.
For a comprehensive introduction, read Workflow for PHP on Rodolfo's blog.
License
Copyright Rodolfo Berrios A.
This software is licensed under the Apache License, Version 2.0. See LICENSE for the full license text.
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
All versions of workflow with dependencies
amphp/amp Version ^3.1
chevere/action Version ^3.0.2
chevere/caller Version ^1.0.0
chevere/container Version ^1.0.5
chevere/data-structure Version ^1.1.0
chevere/filesystem Version ^2.0
chevere/parameter Version ^2.0.5
chevere/regex Version ^1.0.2
spatie/php-structure-discoverer Version ^2.3.2||^2.4