PHPackages                             coroq/flow - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. coroq/flow

ActiveLibrary

coroq/flow
==========

v7.0.0(3y ago)0225[1 PRs](https://github.com/ozami/coroq-flow/pulls)2MITPHPPHP &gt;=7.2CI passing

Since Mar 3Pushed 3mo ago1 watchersCompare

[ Source](https://github.com/ozami/coroq-flow)[ Packagist](https://packagist.org/packages/coroq/flow)[ RSS](/packages/coroq-flow/feed)WikiDiscussions master Synced 1mo ago

READMEChangelog (5)Dependencies (4)Versions (21)Used By (2)

Flow
====

[](#flow)

Flow is a lightweight PHP library designed to manage multi-step control flow in an organized and efficient manner.

Requirements
------------

[](#requirements)

- PHP &gt;= 7.2
- Psr/container

Installation
------------

[](#installation)

Install the library using Composer:

```
composer require coroq/flow
```

Usage
-----

[](#usage)

### Basic

[](#basic)

```
use Coroq\Flow\Flow;

// Let's create a new Flow instance.
$flow = new Flow();

// The Flow manages a collection of values in an associative array.
// To get started, we set the value of 'x' to 1.
$flow->setValues(['x' => 1]);

// Now we'll prepare the steps for our flow.
// Steps can be any callable that returns an array or null.

// First step: using a closure.
// Our function receives its arguments from the values based on their names.
// The value of $x is taken from the value with the key 'x' above, which is 1.
$step1 = function($x) {
  // We return an array that will be merged with the existing values.
  // After this step, our values will be ['x' => 1, 'y' => 2].
  return ['y' => $x + 1];
};

// Second step: using a class with an __invoke magic method.
class Step2 {
  // Don't worry about the order of parameters; only names are used for argument binding.
  // Type hints (like int) don't affect argument binding.
  public function __invoke(int $y, int $x): array {
    // To update a value, return an array with the same key.
    // Since we only return the 'y' key, 'x' will not be changed.
    // After this step, our values will be ['x' => 1, 'y' => 3].
    return ['y' => $x + $y];
  }
}
$step2 = new Step2();

// Third step: using a regular function.
// Only list the parameters you need for the step.
// Here, $z will be null since there's no 'z' key in the values array.
function step3($y, $z) {
  if ($z === null) {
    return ['z' => $y * 2];
  }
  // If you return null, the values won't change.
}

// Add the steps to the flow in the order you want them to execute.
$flow->appendStep($step1);
$flow->appendStep($step2);
$flow->appendStep('step3');

// Execute!
$flow();

// The result will be ['x' => 1, 'y' => 3, 'z' => 6].
$result = $flow->getValues();

// Need a single value? Use getValue().
$z = $flow->getValue('z');

// For a shorter version, create a flow with the steps directly.
// Pass the initial value as an argument, and the Flow will return the result.
$flow = new Flow([$step1, $step2, 'step3']);
$result = $flow(['x' => 1]);

// The shortest version of all.
$result = Flow::call([$step1, $step2, 'step3'], ['x' => 1]);
```

### Nesting `Flow`

[](#nesting-flow)

```
function initializeMessage() {
  return ['message' => 'hello world'];
}

function appendExclamationMark(string $message) {
  $message .= '!';
  return compact('message');
}

$makeMessage = new Flow(['initializeMessage', 'appendExclamationMark']);

function convertToUppercase(string $message) {
  $message = strtoupper($message);
  return compact('message');
}

$makeMessageInUppercase = new Flow([
  $makeMessage, // A Flow object can be a step of another Flow
  'convertToUppercase',
]);

$result = $makeMessageInUppercase([]);
// $result will be ['message' => 'HELLO WORLD!'].
```

### Breaking the flow

[](#breaking-the-flow)

This example demonstrates how to break the flow when a certain condition is met.

```
// First step
// $thisFlow is a special argument representing the Flow instance executing this step.
function checkUserLoggedIn(Flow $thisFlow, $authenticationService, $responseFactory) {
  // If the user is not logged in, we stop the flow
  if (!$authenticationService->isLoggedIn()) {
    $thisFlow->break();
    // You can return a result after breaking the flow
    // In this case, we return a 'forbidden' response
    return ['response' => $responseFactory->createResponse(403)];
  }
}

class ProfileController {
  // Second step
  public static function edit($request, $responseFactory): array {
    // ...
  }
}

// Create and execute the Flow with the necessary dependencies
$controller = new Flow([
  'checkUserLoggedIn',
  'ProfileController::edit',
]);
$result = $controller([
  'authenticationService' => new AuthenticationService(),
  'responseFactory' => $responseFactory,
  'request' => $requestFactory->createServerRequest(...),
]);
```

### Integration with a DI Container

[](#integration-with-a-di-container)

Flow offers a convenient way to integrate a DI Container by fetching default values from an external data source. This allows for seamless integration with your preferred DI Container.

```
use Coroq\Flow\Flow;
use Coroq\Flow\DefaultValueProvider\Psr11ContainerAdapter;

// Set up a DI container implementing the PSR-11 ContainerInterface, and add some dependencies
$diContainer = new SomeDiContainer();
$diContainer->set('userRepository', $userRepositoryFactory);

// Define a step that uses an item from the container
$step = function(UserRepositoryInterface $userRepository) {
  // ...
};

$flow = new Flow([$step]);
// Set the container as the default value provider
$flow->setDefaultValueProvider(new Psr11ContainerAdapter($diContainer));
$result = $flow();
```

License
-------

[](#license)

This project is licensed under the MIT License.

###  Health Score

38

—

LowBetter than 85% of packages

Maintenance53

Moderate activity, may be stable

Popularity11

Limited adoption so far

Community11

Small or concentrated contributor base

Maturity67

Established project with proven stability

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~144 days

Recently: every ~286 days

Total

14

Last Release

1126d ago

Major Versions

v2.1.0 → v3.0.02018-08-31

v3.0.1 → v4.0.02018-12-10

v4.1.0 → v5.0.02020-02-29

v5.0.0 → v6.0.02020-04-04

v6.2.0 → v7.0.02023-04-17

PHP version history (2 changes)v1.0PHP &gt;=5.4

v7.0.0PHP &gt;=7.2

### Community

Maintainers

![](https://www.gravatar.com/avatar/addac0ea12d91786ce888c91ef7de6525bc17252c702cd7e48fe64ab547c012e?d=identicon)[ozami](/maintainers/ozami)

---

Top Contributors

[![ozami](https://avatars.githubusercontent.com/u/170309?v=4)](https://github.com/ozami "ozami (47 commits)")

###  Code Quality

TestsPHPUnit

Static AnalysisPHPStan

Type Coverage Yes

### Embed Badge

![Health badge](/badges/coroq-flow/health.svg)

```
[![Health](https://phpackages.com/badges/coroq-flow/health.svg)](https://phpackages.com/packages/coroq-flow)
```

###  Alternatives

[pimple/pimple

Pimple, a simple Dependency Injection Container

2.7k130.5M1.4k](/packages/pimple-pimple)[neos/flow

Flow Application Framework

862.0M451](/packages/neos-flow)[api-platform/state

API Platform state interfaces

223.4M57](/packages/api-platform-state)[internal/dload

Downloads binaries.

98142.7k10](/packages/internal-dload)[symfony/json-streamer

Provides powerful methods to read/write data structures from/into JSON streams.

14440.0k8](/packages/symfony-json-streamer)[rubix/server

Deploy your Rubix ML models to production with scalable stand-alone inference servers.

632.3k](/packages/rubix-server)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
