PHPackages                             talesoft/tale-collection - 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. talesoft/tale-collection

ActiveLibrary

talesoft/tale-collection
========================

00PHP

Since Sep 10Pushed 7y ago3 watchersCompare

[ Source](https://github.com/Talesoft/tale-collection)[ Packagist](https://packagist.org/packages/talesoft/tale-collection)[ RSS](/packages/talesoft-tale-collection/feed)WikiDiscussions master Synced 2mo ago

READMEChangelogDependenciesVersions (1)Used By (0)

[![Packagist](https://camo.githubusercontent.com/e57c28da64f933f339e69bccb8a4fadce72000e0a23a2695171d6d3d67f3c44f/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f74616c65736f66742f74616c652d636f6c6c656374696f6e2e7376673f7374796c653d666f722d7468652d6261646765)](https://packagist.org/packages/talesoft/tale-collection)[![License](https://camo.githubusercontent.com/aeccec597d3923c65db9944f3e6a329c228f543011287e3aa339ac9eaf094a30/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f6c6963656e73652f54616c65736f66742f74616c652d636f6c6c656374696f6e2e7376673f7374796c653d666f722d7468652d6261646765)](https://github.com/Talesoft/tale-collection/blob/master/LICENSE.md)[![CI](https://camo.githubusercontent.com/2ba5466aef3495fb94bef1580bd268a95f4f64c525e8ddc9386a10faa02f04de/68747470733a2f2f696d672e736869656c64732e696f2f7472617669732f54616c65736f66742f74616c652d636f6c6c656374696f6e2e7376673f7374796c653d666f722d7468652d6261646765)](https://travis-ci.org/Talesoft/tale-collection)[![Coverage](https://camo.githubusercontent.com/9e76cea10371ea963c0631642f154293351a2a3635eb44cdb4dc84fb6ddb25ae/68747470733a2f2f696d672e736869656c64732e696f2f636f6465636c696d6174652f636f7665726167652f54616c65736f66742f74616c652d636f6c6c656374696f6e2e7376673f7374796c653d666f722d7468652d6261646765)](https://codeclimate.com/github/Talesoft/tale-collection)

Tale Collection
===============

[](#tale-collection)

What is Tale Collection?
------------------------

[](#what-is-tale-collection)

Tale Collection is a heavily iterator-based Collection implementation for PHP.

It comes with a generic Collection class that handles chained iteration well as well as a Map and Set implementation with a solid API.

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

[](#installation)

```
composer require talesoft/tale-collection
```

Usage
-----

[](#usage)

### Collection

[](#collection)

#### Signature

[](#signature)

```
Tale\collection(iterable $iterable): Tale\CollectionInterface
//or
new Tale\Collection(iterable $iterable)
```

#### Examples

[](#examples)

```
use function Tale\collection;

$collection = collection(['a', 'b', 'c', 'd']))
    ->filter(function (string $char) {
        return $char !== 'b';
    })
    ->map(function (string $char) {
        return strtoupper($char)
    })
    ->flip();

var_dump($collection['c']); //int(2)
var_dump($collection->toArray());
/*
array(3) {
  'a' => int(0)
  'c' => int(2)
  'd' => int(3)
}
*/
```

As stated, it's heavily iterator-based, so many stacked operations won't ever turn anything into an actual array unless you actually access the data.

Let's demonstrate!

```
use function Tale\collection;

funuction generateAtoZ()
{
    //Imagine this is some hard work
    yield from range('a', 'z');
}

$collection = collection(generateAtoZ())
    //We filter all a-s
    ->filter(function (string $char) {
        return $char !== 'a';
    })
    //We also chain a normal SPL RegexIterator and drop all i to z-s
    ->chain(\RegexIterator::class, '/[^i-z]/')
    //Uppercase all characters
    ->map(function (string $char) {
        return strtoupper($char);
    })
    //Flip the keys and values
    ->flip()
    //Drop characters with the index 3 (this will be 'C')
    ->filter(function (int $index) {
        return $index !== 2;
    })
    //Flip again
    ->flip()
    //Only yield the values (array_values, basically)
    ->getValues();

//This right below is the _first_ part where generateAtoZ will
//actually be triggered at all! Until then we basically did nothing
//except for chaining some iterators

var_dump($collection[2]); //string(1) "E"

//Notice how it's E, because we dropped A and C

var_dump($collection->toArray());
/*
array(6) {
  [0] => string(1) "B"
  [1] => string(1) "D"
  [2] => string(1) "E"
  [3] => string(1) "F"
  [4] => string(1) "G"
  [5] => string(1) "H"
}
*/
```

**Most** methods of Tale collections return collections again. Collections don't only contain arrays, but can also contain an iterable. The iterable will be passed through most methods you work with and will only be lazy-triggered when you access keys or cast it to an array.

This gives the possibility to deeply modify iterable values without creating array copies all over.

In fact, **not a single** of the methods called in the example above except for `toAray()` ever triggered the `generateAtoZ()` generator, not even `getValues()` or `flip()`. They all return collections containing a nested specific iterator.

This also leads to some nice side-effects, like `flip()` not overwriting values.

Imagine we want to do something with the keys of an array without overwriting its values when flipping (very memory efficiently):

```
use function Tale\collection;

$values = collection(['a' => 2, 'b' => 2, 'c' => 3])
    ->flip()
    ->map(function (string $key) {
        return strtoupper($key);
    })
    ->flip();

var_dump($values->toArray());
/*
array(3) {
  'A' => int(2)
  'B' => int(2)
  'C' => int(3)
}
*/
```

To understand what happened, let's look at the native PHP equivalent

```
use function Tale\collection;

$values = array_flip(['a' => 2, 'b' => 2, 'c' => 3]);
//Here our values are lost already, it will result in
// [2 => 'b', 3 => 'c'], as keys are unique

$values = array_map(function (string $key) {
    return strtoupper($key);
}, $values);

$values = array_flip(['a' => 2, 'b' => 2, 'c' => 3]);

var_dump($values);
/*
array(2) {
  ["B"]=> int(2)
  ["C"]=> int(3)
}
*/
```

Through the way iterators work, the values are simply never reduced to an actual array, only when retrieving the end-result. Duplicate keys are no problem during iteration and will always stay available until the iterable gets casted to an array internally.

Specialized collections
-----------------------

[](#specialized-collections)

All of the following collections use the same iterator mechanisms as the collection class discussed above. In fact, there is the `Tale\CollectionInterface` they all implement and all of them use a common base class `Tale\AbstractCollection` that defines most of their APIs.

### Set

[](#set)

The Set class is an abstraction for a set of values where keys don't matter. The keys of a set will be managed and always stay sequential.

The values will be unique. If a value already exists in the set, it won't be added again when using `add`.

The content is managed via the following API:

##### Set-&gt;has($item)

[](#set-hasitem)

Checks if the set contains a specific item

##### Set-&gt;add($item)

[](#set-additem)

Adds a new item to the set

##### Set-&gt;remove($item)

[](#set-removeitem)

Removes an item from the set

```
use function Tale\set;

$existingObject = new SomeClass();

$set = set();
$set->add(new SomeOtherClass());

var_dump($set->has($existingObject)); //bool(true)

var_dump($set->toArray());
/*
array(3) {
  0 => object(SomeOtherClass)#1 (0) {}
  1 => object(SomeClass)#2 (0) {}
}
*/
```

#### Common use-cases

[](#common-use-cases)

**A set of CSS classes on elements**

```
use function Tale\set;

$classList = set(['btn']);

if ($primary) {
    $classList->add('btn-primary');
}

if ($block) {
    $classList->add('btn-block');
}

if ($classList->has('primary') {
    echo "This is a primary button!\n";
}

echo "My button!";
```

### Map

[](#map)

The map is a data structure that allows using keys other than strings and integers. Through limitations of the PHP engine, you can't access complex keys via array access (`[$obj]`).

The following API manages a map:

##### Map-&gt;get($key)

[](#map-getkey)

Retrieves the value for a specific key

##### Map-&gt;set($key, $value)

[](#map-setkey-value)

Sets the value for a specific key

##### Map-&gt;has($key)

[](#map-haskey)

Checks whether a specific key exists or not

##### Map-&gt;remove($key)

[](#map-removekey)

Removes a value with a specific key from the map

```
use function Tale\map;

$key1 = new Key1();
$key2 = new Key2();

$map = map();
$map->set($key1, 'value 1');
$map->set($key2, 'value 2');

var_dump($map->toArray());
/*
array(3) {
  0 => array(2) {
    0 => object(SomeOtherClass)#1 (0) {}
    1 => string(7) "value 1"
  }
  1 => array(2) {
    0 => object(SomeClass)#2 (0) {}
    1 => string(7) "value 2"
  }
}
*/
```

#### Common use-cases

[](#common-use-cases-1)

**A metadata storage for objects**

```
use function Tale\map;

$metadata = map();

$b = new B();

$objects = [
    new A(),
    $b,
    new C(),
    new D()
];

foreach ($objects as $obj) {
    $metadata->set($obj, getMetadataForObject($obj));
}

//[...]

if ($metadata->has($b)) {
    $bMetadata = $metadata->get($b);

    //$bMetadata is now the metadata for the $b instance
}
```

TODO: More docs.

###  Health Score

18

—

LowBetter than 8% of packages

Maintenance20

Infrequent updates — may be unmaintained

Popularity0

Limited adoption so far

Community8

Small or concentrated contributor base

Maturity40

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.

### Community

Maintainers

![](https://www.gravatar.com/avatar/75a80e0830e63c723808d021d3a1648a2643db60f4ac2e40842da05f227f956b?d=identicon)[TorbenKoehn](/maintainers/TorbenKoehn)

---

Top Contributors

[![TorbenKoehn](https://avatars.githubusercontent.com/u/1403556?v=4)](https://github.com/TorbenKoehn "TorbenKoehn (10 commits)")

### Embed Badge

![Health badge](/badges/talesoft-tale-collection/health.svg)

```
[![Health](https://phpackages.com/badges/talesoft-tale-collection/health.svg)](https://phpackages.com/packages/talesoft-tale-collection)
```

PHPackages © 2026

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