PHPackages                             php-kit/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. [Utility &amp; Helpers](/categories/utility)
4. /
5. php-kit/flow

ActiveLibrary[Utility &amp; Helpers](/categories/utility)

php-kit/flow
============

Iterator Nirvana for PHP

2.0.0(9mo ago)32.3k7MITPHPCI passing

Since Dec 6Pushed 9mo ago4 watchersCompare

[ Source](https://github.com/php-kit/flow)[ Packagist](https://packagist.org/packages/php-kit/flow)[ Docs](https://github.com/php-kit/flow)[ RSS](/packages/php-kit-flow/feed)WikiDiscussions master Synced yesterday

READMEChangelogDependenciesVersions (7)Used By (7)

Flow
====

[](#flow)

##### Iterator Nirvana for PHP

[](#iterator-nirvana-for-php)

Runtime requirements
--------------------

[](#runtime-requirements)

- PHP &gt;= 8.0 (fully compatible with PHP 8.4)
- The Standard PHP Library (SPL), which ships with PHP by default

Why fluent iterators?
---------------------

[](#why-fluent-iterators)

PHP has a rich set of iterators and other data processing tools - like the iterators in the Standard PHP Library (SPL) - but they are often not used to their full potential, as they are cumbersome to use and require a lot of boilerplate code.

Flow provides a fluent interface to assemble chains of iterators and other data processing operations, making it easy to write complex data processing pipelines in a concise and readable way.

Instead of collecting values into arrays and managing nested `foreach` loops manually, you compose small, intention-revealing operations that stream data from one step to the next.

The expressive syntax makes it **easy and enjoyable** to build sophisticated processing pipelines while keeping **memory usage low** and the intent of each transformation crystal clear.

### Example: data crunching in one expression

[](#example-data-crunching-in-one-expression)

```
use PhpKit\Flow\Flow;

$topCustomers = Flow::from($orders)
    ->expand(fn ($order) => $order['line_items'])
    ->map(fn ($item) => $item['customer'])
    ->where(fn ($customer) => $customer['active'])
    ->mapAndFilter(function ($customer, &$key) {
        $key = $customer['id'];
        return $customer['total_spent'] > 1000 ? $customer : null;
    })
    ->sort('arsort')
    ->only(10)
    ->all();
```

The same workflow using temporary arrays and for-loops would be longer, harder to read and would duplicate values in memory multiple times.

A Flow pipeline keeps the computation streaming, lets you re-use SPL iterators seamlessly and makes experimentation as simple as inserting or removing a step.

Flow is **not** the usual Collection-style utility library
----------------------------------------------------------

[](#flow-is-not-the-usual-collection-style-utility-library)

Although many libraries exist for implementing collections (e.g. Laravel Collections), Flow is different, even though, on the surface, it seems similar, as it also provides a chainable fluent interface.

Typical Collection-like classes use arrays underneath. But Flow (most of the time) **does not**.

Flow is both an `Iterator` and a `Traversable` (therefore with native PHP support), and works perfectly with **Generators**, **SPL iterators** and `foreach` loops.

Each iteration step only requires **one value** to be in memory (and it can be generated on the fly), and the data is streamed through the pipeline, with **no intermediate storage** and **without needless data copying**.

You can use a Flow object anywhere an `Iterator` or `Traversable` interface is expected. For example, you can use `foreach` directly over a Flow object:

```
foreach (Flow::from([1, 2, 3]) as $value) {
    echo $value;
}
```

You can also pass Flow objects to any function that expects an `Iterator` or `Traversable`:

```
// Flow works seamlessly with SPL functions
$count = iterator_count(Flow::from([1, 2, 3])->where(fn($x) => $x > 1));

// Or with any function expecting a Traversable
function processItems(Traversable $items) {
    foreach ($items as $item) {
        // process each item
    }
}

processItems(Flow::from($data)->map($transformer));
```

You can even generate values on the fly:

```
$values = Flow::from(function () {
    for ($i = 1; $i
