PHPackages                             bastman/php7-arrayly - 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. bastman/php7-arrayly

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

bastman/php7-arrayly
====================

a simple port of Kotlin Collections to php

0.2.1(8y ago)1022MITPHPPHP &gt;=7.1.0

Since May 4Pushed 8y ago1 watchersCompare

[ Source](https://github.com/bastman/php7-Arrayly)[ Packagist](https://packagist.org/packages/bastman/php7-arrayly)[ Docs](https://github.com/bastman/php7-Arrayly)[ RSS](/packages/bastman-php7-arrayly/feed)WikiDiscussions master Synced 2d ago

READMEChangelog (10)Dependencies (1)Versions (18)Used By (0)

php7-Arrayly
============

[](#php7-arrayly)

- ArrayMap (eager): decorates php array with immutable HashMap-style methods similar to Java Streams / Kotlin Collections
- ArrayList (eager): decorates php array\_values($array) with immutable List-style methods
- Sequence (lazy-ish, consume-once): provides fluid interface to php generators &amp; iterators
- Flow (lazy-ish, consume-rewindable, FBP): kind of flow-based-programming-style (FBP) for replayable transformation pipelines

inspired by

- nikic/iter:
- Kotlin Collections:
- Java Stream API:
- Stringy (OO-Style decorator for strings):

Alternative Concepts
--------------------

[](#alternative-concepts)

- Transducers:
- Pipeline, e.g.:

Install
-------

[](#install)

```
$ composer require bastman/php7-arrayly 0.2.1

```

Notes
-----

[](#notes)

- Beta. Happy Testing ;)

Licence
-------

[](#licence)

- MIT. Do whatever you like with that code.

Design Principles
-----------------

[](#design-principles)

- functional programming
- immutability
- strictly strong typing
- composition over inheritance hell

Methods
-------

[](#methods)

- filter, map, flatMap, reduce, groupBy, find, sort, chunk, take, drop, ...

Alternative PHP Collection Frameworks
-------------------------------------

[](#alternative-php-collection-frameworks)

e.g.:

- knapsak:
- functional-php:
- laravel:
- cake:
- hhvm/hack:

Examples (ArrayMap)
-------------------

[](#examples-arraymap)

- see: tests/examples/arrayly

    ```
          mapOfIterable($cities)

          ->map(function ($item) {return $item["country"];})
          ->filter(function ($country) {return $country == 'Germany';})
          ->sortByDescending(function ($a, $b) {return strcasecmp($a, $b);})
          ->drop(1)
          ->take(2)

          ->toArray();

    ```
- ```
          mapOfIterable($cities)
                      ->groupBy(function (array $item):string {
                          return $item["country"];
                      })
                      ->flatMap(function (array $itemGroup):array {
                          return $itemGroup;
                      })
                      ->reverse()
                      ->reduce('', function (string $acc, array $item):string {
                          return $acc . ':' . $item["city"];
                      });

    ```

Examples (ArrayList)
--------------------

[](#examples-arraylist)

- ```
          listOf("a1", "a2", "b1", "a3")

          ->map(function ($value) {return strtoupper($value);})
          ->filter(function ($value) {return fnmatch("*A*", $value);})
          ->sortByDescending(function ($a, $b) {return strcasecmp($a, $b);})
          ->drop(1)
          ->take(2)

          ->toArray();

    ```
- ```
          listOfIterable($cities)

                      ->groupBy(function (array $item):string {
                          return $item["country"];
                      })
                      ->flatMap(function (array $itemGroup):array {
                          return $itemGroup;
                      })
                      ->reverse()
                      ->reduce('', function (string $acc, array $item):string {
                          return $acc . ':' . $item["city"];
                      });

    ```

Examples (Sequence) - uses generators approach
----------------------------------------------

[](#examples-sequence----uses-generators-approach)

- see: tests/examples/sequence

    ```
           sequenceOfIterable($cities)

            ->filter(function (array $v):bool {
                return $v['country']==='Germany';
            })
            ->map(function(array $v):array{
                return $v;
            })
            ->groupBy(function (array $v):string {
                return $v['country'];
            })
            ->flatMap(function (array $itemGroup):array {
                return $itemGroup;
            })
            ->pipe(function(iterable $iterable){
                foreach ($iterable as $k=>$v) {
                    yield $k=>$v;
                }
            })

            ->collect()
            ->toArray();

    ```

Examples (Flow) - Flow Based Programming (FBP)
----------------------------------------------

[](#examples-flow----flow-based-programming-fbp)

- see: tests/examples/flow

1. ```
     // define the re-usable flow
     $flow = Flow::create()
         ->filter(function (array $v): bool {
             return $v['country'] === 'Germany';
         })
         ->map(function (array $v): array {
             return $v;
         })
         ->groupBy(function (array $v): string {
             return $v['country'];
         })
         ->flatMap(function (array $itemGroup): array {
             return $itemGroup;
         });

    ```
2. ```
     // run the flow with a given producer
     $cities = self::createCities();
     $sink = $flow->withProducerOfIterable($cities)
         ->collect()
         ->toArray();

    ```
3. ```
     // derive a new flow by applying a different producer
     // note: the old flow will not be affected by this. immutability rockz :)

     $derivedFlow = $flow->withProducerOfIteratorSupplier(
             function():\Generator {
                 yield from self::createCities();
             });

    ```
4. ```
     // run the derived flow
     $sink = $derivedFlow
         ->collect()
         ->toArray();

    ```
5. ```
     // and re-run the derived flow - because we can ;)
     $sink = $derivedFlow
         ->collect()
         ->toArray();

    ```

Api (Source: top-level-functions)
---------------------------------

[](#api-source-top-level-functions)

```
function listOf(...$values):ArrayList
function listOfIterable(iterable $iterable):ArrayList
function mapOfIterable(iterable $iterable):ArrayMap
function sequenceOfIterable(iterable $iterable):Sequence
function sequenceOfIteratorSupplier(\Closure $supplier):Sequence
function sequenceOfRewindableIteratorSupplier(\Closure $supplier):Sequence

```

Api (Sink)
----------

[](#api-sink)

```
public function toArray(): array;

public function toGenerator(): \Generator;

public function toSequence(): Sequence;

public function toMap(): ArrayMap;

public function toList(): ArrayList;

public function getIterator(): \Generator;

public function toIteratorSupplier(): \Closure;

```

Api (ArrayMap)
--------------

[](#api-arraymap)

```
public function collect(): Sink;

public function toArray(): array;

public function getIterator(): \Generator;

public function copy(): ArrayMap;

public function withData(array $data): ArrayMap;

public function withKey($key, $value): ArrayMap;

public function keys(bool $strict = true): ArrayMap;

public function values(): ArrayMap;

public function flip(): ArrayMap;

public function shuffle(int $times): ArrayMap;

public function count(): int;

public function reverse(): ArrayMap;

public function hasKey($key): bool;

public function firstOrNull();

public function firstOrDefault($defaultValue);

public function firstOrElse(\Closure $defaultValueSupplier);

public function getOrElse($key, \Closure $defaultValueSupplier);

public function getOrNull($key);

public function getOrDefault($key, $defaultValue);

public function findOrNull(\Closure $predicate);

public function findOrDefault(\Closure $predicate, $defaultValue);

public function findOrElse(\Closure $predicate, \Closure $defaultValueSupplier);

public function findIndexedOrNull(\Closure $predicate);

public function findIndexedOrDefault(\Closure $predicate, $defaultValue);

public function findIndexedOrElse(\Closure $predicate, \Closure $defaultValueSupplier);

public function onEach(\Closure $callback): ArrayMap;

public function onEachIndexed(\Closure $callback): ArrayMap;

public function filter(\Closure $predicate): ArrayMap;

public function filterIndexed(\Closure $predicate): ArrayMap;

public function filterNot(\Closure $predicate): ArrayMap;

public function filterNotIndexed(\Closure $predicate): ArrayMap;

public function filterNotNull(): ArrayMap;

public function map(\Closure $transform): ArrayMap;

public function mapIndexed(\Closure $transform): ArrayMap;

public function mapKeysByValue(\Closure $keySelector): ArrayMap;

public function mapKeysByValueIndexed(\Closure $keySelector): ArrayMap;

public function flatMap(\Closure $transform): ArrayMap;

public function flatMapIndexed(\Closure $transform): ArrayMap;

public function groupBy(\Closure $keySelector): ArrayMap;

public function groupByIndexed(\Closure $keySelector): ArrayMap;

public function reduce($initialValue, \Closure $reducer);

public function reduceIndexed($initialValue, \Closure $reducer);

public function sortedBy(\Closure $comparator, bool $descending): ArrayMap;

public function sortBy(\Closure $comparator): ArrayMap;

public function sortByDescending(\Closure $comparator): ArrayMap;

public function take(int $amount): ArrayMap;

public function takeWhile(\Closure $predicate): ArrayMap;

public function takeWhileIndexed(\Closure $predicate): ArrayMap;

public function takeLast(int $amount): ArrayMap;

public function drop(int $amount): ArrayMap;

public function dropWhile(\Closure $predicate): ArrayMap;

public function dropWhileIndexed(\Closure $predicate): ArrayMap;

public function chunk(int $batchSize): ArrayMap;

public function slice(? $startIndex, ? $stopIndexExclusive, int $step = 1): ArrayMap;

public function sliceByOffsetAndLimit(int $offset, ? $limit, int $step = 1): ArrayMap;

```

Api (ArrayList)
---------------

[](#api-arraylist)

```
public function collect(): Sink;

public function toArray(): array;

public function getIterator(): \Generator;

public function copy(): ArrayList;

public function withData(array $data): ArrayList;

public function keys(bool $strict = true): ArrayList;

public function values(): ArrayList;

public function flip(): ArrayList;

public function shuffle(int $times): ArrayList;

public function count(): int;

public function reverse(): ArrayList;

public function hasElementAt(int $index): bool;

public function firstOrNull();

public function firstOrDefault($defaultValue);

public function firstOrElse(\Closure $defaultValueSupplier);

public function getOrElse(int $index, \Closure $defaultValueSupplier);

public function getOrNull(int $index);

public function getOrDefault(int $index, $defaultValue);

public function findOrNull(\Closure $predicate);

public function findOrDefault(\Closure $predicate, $defaultValue);

public function findOrElse(\Closure $predicate, \Closure $defaultValueSupplier);

public function findIndexedOrNull(\Closure $predicate);

public function findIndexedOrDefault(\Closure $predicate, $defaultValue);

public function findIndexedOrElse(\Closure $predicate, \Closure $defaultValueSupplier);

public function onEach(\Closure $callback): ArrayList;

public function onEachIndexed(\Closure $callback): ArrayList;

public function filter(\Closure $predicate): ArrayList;

public function filterIndexed(\Closure $predicate): ArrayList;

public function filterNot(\Closure $predicate): ArrayList;

public function filterNotIndexed(\Closure $predicate): ArrayList;

public function filterNotNull(): ArrayList;

public function map(\Closure $transform): ArrayList;

public function mapIndexed(\Closure $transform): ArrayList;

public function flatMap(\Closure $transform): ArrayList;

public function flatMapIndexed(\Closure $transform): ArrayList;

public function groupBy(\Closure $keySelector): ArrayMap;

public function groupByIndexed(\Closure $keySelector): ArrayMap;

public function reduce($initialValue, \Closure $reducer);

public function reduceIndexed($initialValue, \Closure $reducer);

public function sortedBy(\Closure $comparator, bool $descending): ArrayList;

public function sortBy(\Closure $comparator): ArrayList;

public function sortByDescending(\Closure $comparator): ArrayList;

public function take(int $amount): ArrayList;

public function takeWhile(\Closure $predicate): ArrayList;

public function takeWhileIndexed(\Closure $predicate): ArrayList;

public function takeLast(int $amount): ArrayList;

public function drop(int $amount): ArrayList;

public function dropWhile(\Closure $predicate): ArrayList;

public function dropWhileIndexed(\Closure $predicate): ArrayList;

public function chunk(int $batchSize): ArrayList;

public function slice(? $startIndex, ? $stopIndexExclusive, int $step = 1): ArrayList;

public function sliceByOffsetAndLimit(int $offset, ? $limit, int $step = 1): ArrayList;

```

Api (Sequence)
--------------

[](#api-sequence)

```
public static function ofIteratorSupplier(\Closure $supplier): Sequence;

public function withData(iterable $data): Sequence;

public function collect(): Sink;

public function forEachRemaining(\Closure $callback): Void;

public function reducing($initialValue, \Closure $reducer): Sequence;

public function reducingIndexed($initialValue, \Closure $reducer): Sequence;

public function pipe(\Closure $transform): Sequence;

public function keys(): Sequence;

public function values(): Sequence;

public function flip(): Sequence;

public function reverse(): Sequence;

public function onEach(\Closure $callback): Sequence;

public function onEachIndexed(\Closure $callback): Sequence;

public function map(\Closure $transform): Sequence;

public function mapIndexed(\Closure $transform): Sequence;

public function mapKeysByValue(\Closure $keySelector): Sequence;

public function mapKeysByValueIndexed(\Closure $keySelector): Sequence;

public function filter(\Closure $predicate): Sequence;

public function filterIndexed(\Closure $predicate): Sequence;

public function filterNot(\Closure $predicate): Sequence;

public function filterNotIndexed(\Closure $predicate): Sequence;

public function filterNotNull(): Sequence;

public function flatMap(\Closure $transform): Sequence;

public function flatMapIndexed(\Closure $transform): Sequence;

public function groupBy(\Closure $keySelector): Sequence;

public function groupByIndexed(\Closure $keySelector): Sequence;

public function take(int $amount): Sequence;

public function takeWhile(\Closure $predicate): Sequence;

public function takeWhileIndexed(\Closure $predicate): Sequence;

public function takeLast(int $amount): Sequence;

public function drop(int $amount): Sequence;

public function dropWhile(\Closure $predicate): Sequence;

public function dropWhileIndexed(\Closure $predicate): Sequence;

public function sortedBy(bool $descending, \Closure $comparator): Sequence;

public function sortBy(\Closure $comparator): Sequence;

public function sortByDescending(\Closure $comparator): Sequence;

public function chunk(int $batchSize): Sequence;

public function slice(? $startIndex, ? $stopIndexExclusive, int $step = 1): Sequence;

public function sliceByOffsetAndLimit(int $offset, ? $limit, int $step = 1): Sequence;

```

Api (Flow)
----------

[](#api-flow)

```
public static function create(): Flow;

public static function ofRewindableIteratorSupplier(\Closure $supplier): Flow;

public function copy(): Flow;

public function withoutProducer(): Flow;

public function withProducer(RewindableProducer $producer): Flow;

public function withProducerOfIterable(iterable $iterable): Flow;

public function withProducerOfIteratorSupplier(\Closure $iteratorSupplier): Flow;

public function collect(): Sink;

public function reducing($initialValue, \Closure $reducer): Flow;

public function reducingIndexed($initialValue, \Closure $reducer): Flow;

public function pipe(\Closure $transform): Flow;

public function keys(): Flow;

public function values(): Flow;

public function flip(): Flow;

public function reverse(): Flow;

public function onEach(\Closure $callback): Flow;

public function onEachIndexed(\Closure $callback): Flow;

public function map(\Closure $transform): Flow;

public function mapIndexed(\Closure $transform): Flow;

public function mapKeysByValue(\Closure $keySelector): Flow;

public function mapKeysByValueIndexed(\Closure $keySelector): Flow;

public function filter(\Closure $predicate): Flow;

public function filterIndexed(\Closure $predicate): Flow;

public function filterNot(\Closure $predicate): Flow;

public function filterNotIndexed(\Closure $predicate): Flow;

public function filterNotNull(): Flow;

public function flatMap(\Closure $transform): Flow;

public function flatMapIndexed(\Closure $transform): Flow;

public function groupBy(\Closure $keySelector): Flow;

public function groupByIndexed(\Closure $keySelector): Flow;

public function take(int $amount): Flow;

public function takeWhile(\Closure $predicate): Flow;

public function takeWhileIndexed(\Closure $predicate): Flow;

public function takeLast(int $amount): Flow;

public function drop(int $amount): Flow;

public function dropWhile(\Closure $predicate): Flow;

public function dropWhileIndexed(\Closure $predicate): Flow;

public function sortedBy(bool $descending, \Closure $comparator): Flow;

public function sortBy(\Closure $comparator): Flow;

public function sortByDescending(\Closure $comparator): Flow;

public function chunk(int $batchSize): Flow;

public function slice(? $startIndex, ? $stopIndexExclusive, int $step = 1): Flow;

public function sliceByOffsetAndLimit(int $offset, ? $limit, int $step = 1): Flow;

```

###  Health Score

27

—

LowBetter than 49% of packages

Maintenance20

Infrequent updates — may be unmaintained

Popularity13

Limited adoption so far

Community7

Small or concentrated contributor base

Maturity57

Maturing project, gaining track record

 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 ~1 days

Total

17

Last Release

3271d ago

PHP version history (2 changes)0.0.1PHP &gt;=7.0.0

0.0.2PHP &gt;=7.1.0

### Community

Maintainers

![](https://www.gravatar.com/avatar/3d4dc36de40d448c6654dc0b0555c7bf6dbbc5fc374797664ad34792b100b2e9?d=identicon)[bastman](/maintainers/bastman)

---

Top Contributors

[![bastman](https://avatars.githubusercontent.com/u/234912?v=4)](https://github.com/bastman "bastman (2 commits)")

---

Tags

arrayutilityhelpersmanipulationutils

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/bastman-php7-arrayly/health.svg)

```
[![Health](https://phpackages.com/badges/bastman-php7-arrayly/health.svg)](https://phpackages.com/packages/bastman-php7-arrayly)
```

###  Alternatives

[danielstjules/stringy

A string manipulation library with multibyte support

2.4k26.0M191](/packages/danielstjules-stringy)[voku/arrayy

Array manipulation library for PHP, called Arrayy!

4875.5M16](/packages/voku-arrayy)[nette/utils

🛠 Nette Utils: lightweight utilities for string &amp; array manipulation, image handling, safe JSON encoding/decoding, validation, slug or strong password generating etc.

2.1k394.3M1.5k](/packages/nette-utils)[voku/stringy

A string manipulation library with multibyte support

1783.8M19](/packages/voku-stringy)[jbzoo/utils

Collection of PHP functions, mini classes and snippets for everyday developer's routine life.

8321.5M36](/packages/jbzoo-utils)[statamic/stringy

A string manipulation library with multibyte support, forked from @statamic

234.5M14](/packages/statamic-stringy)

PHPackages © 2026

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