darkwood/flow
Flow is a PHP 8.5+ package for building asynchronous pipelines with a functional style. Define steps with generators, pass typed data through each stage, and await execution. Includes examples and docs, with a focus on assembling code as “flows”.
This section provides practical examples demonstrating Flow's capabilities with Y-combinator and asynchronous processing.
This example demonstrates how to adapt the AsyncDecoratorTrait POC to use Flow with Y-combinator and asynchronous processing.
The original AsyncDecoratorTrait POC from SymfonyLive Paris 2023 demonstrates how to:
This Flow adaptation achieves the same goals using:
// HTTP Request Data
class HttpRequestData {
public function __construct(
public int $id,
public string $url,
public array $options = [],
public ?string $method = 'GET'
) {}
}
// HTTP Response Data
class HttpResponseData {
public function __construct(
public int $id,
public string $content,
public int $statusCode,
public array $headers = [],
public ?array $parsedData = null
) {}
}
// Chunk Data (carries data through the flow)
class ChunkData {
public function __construct(
public int $id,
public string $content,
public bool $isFirst = false,
public bool $isLast = false,
public mixed $additionalRequests = null
) {}
}
// Final User Data
class UserData {
public function __construct(
public int $id,
public string $name,
public string $email,
public ?array $availabilities = null,
public ?array $posts = null
) {}
}
The Y-combinator is used in two key places:
// Y-combinator wrapper
$Ywrap = static function (callable $func, callable $wrapperFunc): JobInterface {
$wrappedFunc = static fn ($recurse) => $wrapperFunc(static fn (...$args) => $func($recurse)(...$args));
return new YJob($wrappedFunc);
};
// Usage in Flow
yield new YFlow($processChunksRecursively);
yield [$makeAdditionalRequestsAsync];
php examples/httpchunkflow.php
| Feature | AsyncDecoratorTrait | Flow + Y-Combinator |
|---|---|---|
| Approach | Imperative, callback-based | Functional, flow-based |
| Recursion | Manual loop management | Y-combinator |
| Async | Symfony HttpClient | Flow drivers |
| Data Flow | Mutable state | Immutable data models |
| Error Handling | Try-catch blocks | Flow error jobs |
| Concurrency | Manual management | Built-in Flow support |
| Testing | Complex setup | Simple data flow testing |
Using Flow\Driver\AmpDriver driver
Starting HTTP chunk processing with Flow and Y-combinator...
*. #1 - Making HTTP request to https://jsonplaceholder.typicode.com/users
*. #2 - Making HTTP request to https://jsonplaceholder.typicode.com/users/404
*. #3 - Making HTTP request to https://jsonplaceholder.typicode.com/users
*. #1 - HTTP request completed with status 200 (took 1.0 seconds)
.* #1 - Parsing HTTP response
..* #1 - Processing chunks with Y-combinator
...* #101 - Making additional request to https://jsonplaceholder.typicode.com/users/1/todos
...* #1101 - Making additional request to https://jsonplaceholder.typicode.com/users/1/posts
....* Merging additional data with main response
.....* Finalizing results
User #1: John Doe (john@example.com)
- Todos: 3 items
- Posts: 2 items
Todo examples: Todo 1, Todo 2, Todo 3
Post examples: Post 1, Post 2
Processing completed successfully!
This Flow adaptation demonstrates how to:
The result is a more elegant, testable, and maintainable solution that achieves the same goals as the original AsyncDecoratorTrait POC.
A simple demonstration comparing the AsyncDecoratorTrait approach with Flow + Y-Combinator:
php examples/comparison_demo.php
This demo shows the key differences between the two approaches and highlights the benefits of using Flow for functional programming and asynchronous processing.
How can I help you explore Laravel packages today?