PHPackages                             jeremeamia/iter8 - 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. jeremeamia/iter8

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

jeremeamia/iter8
================

0.1.0(6y ago)4912.4k↓30.6%[1 issues](https://github.com/jeremeamia/iter8/issues)MITPHPPHP &gt;=7.2

Since Jul 19Pushed 6y ago1 watchersCompare

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

READMEChangelog (1)Dependencies (3)Versions (2)Used By (0)

Iter8
=====

[](#iter8)

[![Made with Love](https://camo.githubusercontent.com/c9d06408f6486376904f6b11590fb3171fc7c6303bd73cf11aed28b4a4a998a8/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f6d6164655f776974682d2545322539392541352d6666363962342e737667)](https://github.com/jeremeamia/iter8/graphs/contributors)[![Coded in PHP](https://camo.githubusercontent.com/039d46cfe98d3200978bf674edd768f0edf6855e8198e33decef32d72907fbc6/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f636f64652d706870372d3838393262662e737667)](http://php.net/)[![Packagist Version](https://camo.githubusercontent.com/6aea407a205922be362ba2f537cb79b8d120bf475afa98aca5167297948ba280/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f6a6572656d65616d69612f69746572382e737667)](https://packagist.org/packages/jeremeamia/iter8)[![CircleCI](https://camo.githubusercontent.com/14edb434dcbaa4f44024747e915a4886c8c1bcf1a20ae69b2b23b19bd81dd72e/68747470733a2f2f636972636c6563692e636f6d2f67682f6a6572656d65616d69612f69746572382f747265652f6d61737465722e7376673f7374796c653d737667)](https://circleci.com/gh/jeremeamia/iter8/tree/master)

Introduction
------------

[](#introduction)

Iter8 is a PHP library for iterable and functional operations (e.g., map, filter, reduce) implemented using generators.

Iter8 provides ways to create and transform any `iterable`s (e.g., generators, iterators, arrays, etc.) easily in order to deal with data sets that fit the `Iterator` pattern use case (i.e., typically data of large, paginated, infinite, or unknown length). Using iterators/generators generally provides benefits like lower memory consumption and lazy evaluation. Complex transformations can be defined via functional composition.

Usage
-----

[](#usage)

Iter8's core implementations reside as static methods in 3 classes:

- `Iter` – Operations for iterable values. Some transform (e.g., map, filter) and some evaluate (e.g., reduce).
- `Gen` – Factories for creating iterables from other values.
- `Func` – Utilities for creating or transforming callables to be used with iterable operations.

There are 3 usage patterns for working with iterable values available in Iter8. Which you use is mostly a matter of preference:

- `Iter` functions – Standard function-oriented usage with the `Iter` functions.
- `Pipe` composition – Use of `Iter::pipe()` and the `Pipe::*` functions to compose a set of iterable transformations.
- `Collection` object - An OOP interface to Iter8, that exposes the `Iter::*` and `Gen::*` functions as chainable methods on an a collection-type object.

The examples in the next section will demonstrate each of these usage patterns.

Examples
--------

[](#examples)

Given the following data set...

```
const PEOPLE = [
    ['name' => 'Abby',  'age' => 19],
    ['name' => 'Benny', 'age' => 21],
    ['name' => 'Cally', 'age' => 22],
    ['name' => 'Danny', 'age' => 24],
    ['name' => 'Danny', 'age' => 24],
    ['name' => 'Eddy',  'age' => 18],
];
```

### Iter Functions

[](#iter-functions)

With this usage pattern, operations are applied procedurally and one-at-a-time.

```
$iter = Gen::from(PEOPLE);
$iter = Iter::filter($iter, Func::compose([
    Func::index('age'),
    Func::operator('>=', 20),
]));
$iter = Iter::map($iter, Func::index('name'));
$iter = Iter::debounce($iter);

Iter::print($iter);
#> ['Benny', 'Cally', 'Danny']
```

### Pipe Composition

[](#pipe-composition)

With this usage pattern, operations are "piped" or composed together. The `Pipe` class delegates its operations back to the `Iter` class, but manages the iterable value.

```
$iter = Iter::pipe(Gen::from(PEOPLE), [
    Pipe::filter(Func::compose([
        Func::index('age'),
        Func::operator('>=', 20),
    ])),
    Pipe::map(Func::index('name')),
    Pipe::debounce(),
]);

Iter::print($iter);
#> ['Benny', 'Cally', 'Danny']
```

You can "switch" the context of the iterable you are transforming in the middle of a pipe. This example evaluates the max age from the iterable of people, and then switches to a new iterable using that max age value.

```
$iter = Iter::pipe(Gen::from(PEOPLE), [
    Pipe::pluck('age'),
    Pipe::reduce('max'),
    Pipe::switch(function (int $maxAge) {
        return Gen::range(1, $maxAge);
    }),
]);

Iter::print($iter);
#> [1, 2, 3, ..., 22, 23, 24]
```

### Collection Object

[](#collection-object)

With this usage pattern, the iterable is encapsulated as a `Collection` object. Calling methods on the collection object delegate back to the `Iter` class, but the iterable is managed internally. Collections are immutable, so each transformation returns a new instance. Also, unlike regular generators, collections can be rewound. Static method calls on `Collection` are delegated to `Gen`, so the `Collection` object actually exposes the breadth of Iter8's functionality from one interface.

```
$collection = Collection::from(PEOPLE)
    ->filter(Func::compose([
        Func::index('age'),
        Func::operator('>=', 20),
    ]))
    ->map(Func::index('name'))
    ->debounce();

$collection->print();
#> ['Benny', 'Cally', 'Danny']
```

Rewindability
-------------

[](#rewindability)

Generators are not rewindable (i.e., calling `rewind()` on them explicitly or trying `foreach` them again will cause an error). Iter8 provides two ways to make generators/iterables rewindable.

### Deferred Generators

[](#deferred-generators)

If you are in control of the function that produces the generator (i.e., the one containing the `yield` statements), then you can use the `Gen::defer()` function to wrap that generating function.

```
$items = Gen::defer(function () use ($apiClient) {
    $apiResult = $apiClient->getItems();
    foreach ($apiResult['items'] as $data) {
        yield Models\Item::fromArray($data);
    }
});

// ...
// First iteration
foreach ($items as $item) { /* ... */ }
// ...
// Another iteration
foreach ($items as $item) { /* ... */ }
```

`Gen::defer()` returns a `DeferredGenerator` iterator, that defers producing the actual generator until the time of iteration. If you rewind or iterate again, then the generating function is re-executed.

### Rewindable Iterator

[](#rewindable-iterator)

If you don't control the generating function or want to avoid re-executing the generator, then you can retroactively make the iterable rewindable by using the `Iter::rewindable()` function.

```
$apiResult = $apiClient->getItems();
$items = Iter::map($apiResult['items'], function (array $data) {
    return Models\Item::fromArray($data);
});
$items = Iter::rewindable($items);

// ...
// First iteration
foreach ($items as $item) { /* ... */ }
// ...
// Another iteration
foreach ($items as $item) { /* ... */ }
```

`Iter::rewindable()` wraps the provided iterable in a `RewindableIterator`, which caches items during the first iteration, such that they can be re-emitted in later iterations.

Also, `Collection`s are rewindable be default, since they extend the `RewindableIterator`.

Inspiration
-----------

[](#inspiration)

A lot of my recent work in PHP has dealt with iterators and generators, and fiddling about with large API result sets, so I wanted to put something like this together to share.

However, some work like this has been done before in libraries like [nikic/iter](https://github.com/nikic/iter). You'll notice that I have some similar functions and implementations. Some of my work here is inspired by that library, and some is straight borrowed.

In addition, I've taken some inspiration from the [ReactiveX](http://reactivex.io/) project. Though generators and observables are not identical concepts, they are similar, so some of the operations and names of operations have been borrowed when they apply equally well to both generators and observables. Also, the concept of "pipe" from [RxJS](https://github.com/ReactiveX/rxjs), the JavaScript implementation of ReactiveX, is implemented in this project for composing transformations. In a way, this is also similar to how the [mtdowling/transducers.php](https://github.com/mtdowling/transducers.php) library works with its "composable algorithmic transformations". The idea of "transducers" themselves are [borrowed from Clojure](https://clojure.org/reference/transducers), so I've looked to several sources for ideas.

Finally, I've also taken ideas from the [Laravel Collections](https://laravel.com/docs/5.8/collections) library, and though I also have some similar functions, my implementations vary greatly as they are founded upon generators, not arrays. This means that random array access of values in Iter8 collections is not supported.

###  Health Score

29

—

LowBetter than 59% of packages

Maintenance20

Infrequent updates — may be unmaintained

Popularity34

Limited adoption so far

Community9

Small or concentrated contributor base

Maturity43

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 94.1% 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

Unknown

Total

1

Last Release

2495d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/184fbc398ff1b83855ab8289cd8ce20225d0158c66284b458d2d811546606938?d=identicon)[jeremeamia](/maintainers/jeremeamia)

---

Top Contributors

[![jeremeamia](https://avatars.githubusercontent.com/u/107867?v=4)](https://github.com/jeremeamia "jeremeamia (32 commits)")[![assertchris](https://avatars.githubusercontent.com/u/200609?v=4)](https://github.com/assertchris "assertchris (2 commits)")

---

Tags

functionsgeneratorsiterableiteratorsphptransformationsyield

###  Code Quality

TestsPHPUnit

Static AnalysisPHPStan

Code StylePHP\_CodeSniffer

Type Coverage Yes

### Embed Badge

![Health badge](/badges/jeremeamia-iter8/health.svg)

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

PHPackages © 2026

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