Skip to content

Collections

Collections are a powerful, array-like data structure that allow you to work with your data in a more expressive way than traditional arrays. They are especially useful when working with data that is returned from a database, or when working with JSON data. At their heart they are modelled after the Javascript array functionality, and have been expanded from there.

Collection instances are immutable. This means that any action that would modify the item array will return a new Collection instance containing the results of the previous action, leaving the original data untouched.

A Quick Example

A new collection is created by creating a new instance of Myth\Collection\Collection. You can populate the items in the collection at instantation by passing an array into the constructor.

use Myth\Collection\Collection;

$items = ['a' => 1, 'b' => 2, 'c' => 3, 'd' => 4];
$collection = new Collection($items);

$firstEvenItem = $collection
    ->filter(function($value, $key) {
        return $value % 2 === 0;
    })->first();

You can integrate most of the following methods into your own work by using the Myth\Collection\CollectionTrait within your class.

All collections can be accessed via standard array access:

$items = ['a' => 1, 'b' => 2, 'c' => 3, 'd' => 4];
$collection = new Collection($items);

echo $collection['b'];

Available Methods

at average
count column
diff each
every filter
fill find
findIndex first
flatten groupBy
includes isEmpty
indexOf items
join key
keys last
map merge
next pop
prev push
reduce reverse
serialize shift
slice sort
sortDesc splice
sum take
toArray values
unique valid
when unless
unserialize

Creation

__construct()

An array of items can be passed directly into the constructor at the time of creation.

$collection = new Collection(['foo', 'bar', 'baz']);

of()

Creates a new Collection instance with any number of items in it.

$collection = Collection::of($foo, $bar, $baz);

from($items, $callback)

Creates a new Collection from an iterable class or object.

$items = ['foo', 'bar', 'baz'];
$collection = Collection::from($items);

If $items is a class instance, it will make a collection from its public properties.

class Foo
{
    public $foo = 'foo';
    public $bar = 'bar';
    protected $baz = 'baz';
}

$foo = new Foo();
$collection = Collection::from($foo);

// $collection = ['foo', 'bar']

You can process each element in the collection by passing a callback as the second parameter.

$items = ['foo', 'bar', 'baz'];
$collection = Collection::from($items, function($item) {
    return strtoupper($item);
});

// $collection = ['FOO', 'BAR', 'BAZ']

Item Retrieval

toArray()

Returns the items in the collection as an array.

$collection = new Collection(['foo', 'bar', 'baz']);
return $collection->toArray();
// $collection = ['foo', 'bar', 'baz']

items()

Returns an ArrayIterator with all of the items in the collection.

$collection = new Collection(['foo', 'bar', 'baz']);
return $collection->items();
// returns new ArrayIterator(['foo', 'bar', 'baz'])

serialize()

Returns a serialized version of the collection.

$collection = new Collection(['foo', 'bar', 'baz']);
return $collection->serialize();
// returns 'a:3:{i:0;s:3:"foo";i:1;s:3:"bar";i:2;s:3:"baz";}'

unserialize($items)

Creates a new collection out of a serialized array of items.

$serialized = 'a:3:{i:0;s:3:"foo";i:1;s:3:"bar";i:2;s:3:"baz";}';
$collection = (new Collection())->unserialize($serialized);

first()

Returns the first item in the collection.

$collection = new Collection(['foo', 'bar', 'baz']);
return $collection->first();
// returns 'foo'

last()

Returns the last item in the collection as it is currently sorted.

$collection = new Collection(['foo', 'bar', 'baz']);
return $collection->last();
// returns 'baz'

next()

Returns the next item in the collection.

$collection = new Collection(['foo', 'bar', 'baz']);
return $collection->next();
// returns 'bar'

prev()

Returns the previous item in the collection. If the cursor is currently at the first element, it will return the first element in the array.

$collection = new Collection(['foo', 'bar', 'baz']);
return $collection->prev();
// returns 'foo'

at()

Returns the item at the current offset. If the offset is negative it will return the item in the collection that is offset that many items from the end of the collection. The offset is zero-based.

$collection = new Collection(['foo', 'bar', 'baz']);
return $collection->at(1);
// returns 'bar'

Instance Methods

count()

Returns the total number of items in the collection.

$collection = new Collection(['foo', 'bar', 'baz']);
return $collection->count();
// returns 3

average($key)

Returns the average of all items in the collection. If $key is provided, it will return the average of $key within each item.

$collection = new Collection([1, 2, 3, 4]);
return $collection->average();
// returns 2.5

$collection = new Collection([
    ['foo' => 10],
    ['foo' => 20],
    ['foo' => 30],
    ['foo' => 40],
]);
return $collection->average('foo');
// returns 25

column()

Returns a new collection from the original collection with single column of collection.

$collection = new Collection([
    ['id' => 1, 'name' => 'John'],
    ['id' => 2, 'name' => 'Carter'],
    ['id' => 3, 'name' => 'Steve'],
]);
return $collection->column('name');
// return ['John', 'Carter', 'Steve']

If an index is provided, the values from this column will be used as keys for the returned result in the collection.

$collection = new Collection([
    (object) ['id' => 1, 'name' => 'John'],
    (object) ['id' => 2, 'name' => 'Carter'],
    (object) ['id' => 3, 'name' => 'Steve'],
]);
return $collection->column('name', 'id');
// returns [1 => 'John', 2 => 'Carter', 3 => 'Steve']

diff()

Returns a new collection from the original collection with only different items from passed in array or collection.

$collection = new Collection(['foo', 'bar', 'baz']);
return $collection->diff(['foo', 'baz']);
// returns [1 => 'bar']

You can also pass the column name as a string or multiple columns as array as a second parameter if you work with associative arrays or objects.

$collection = new Collection([
    ['name' => 'John Doe 1', 'age' => 25],
    ['name' => 'Jane Doe 2', 'age' => 30],
    ['name' => 'John Doe 3', 'age' => 25],
]);
return $collection->diff([
    ['name' => 'John Doe 1', 'age' => 25],
    ['name' => 'John Doe 3', 'age' => 25],
], 'name');
// returns [1 => ['name' => 'Jane Doe 2', 'age' => 30]]

each()

Iterates over all items, passing each one into the callable.

$collection->each(function($item, $key) {
    //
});

You can stop iterating through the items by returning false from the callable.

$collection->each(function($item, $key) {
    if (/* condition */) {
        return false;
    }
});

every()

Used to determine if all items in the collection evaluate to true when passed to the given callable.

$collection = new Collection([1, 2, 3, 4]);
$collection->every(function($item) {
    return $item > 2;
});
// returns false

If the $items array is empty, it will return true.

fill($start, $end, $value)

Fills all elements of the collection with a static value. The start value must be provided. If no end index is specified it will fill until the end of the collection.

$collection = new Collection([1, 2, 3, 4, 5]);
return $collection->fill(1, 2, 9);
// returns [1, 9, 9, 4, 5]

filter()

Returns a new collection with only the items that satisfy the given callable by returning a boolean true.

$collection = new Collection([1, 2, 3, 4, 5, 6]);
return $collection->filter(function($item) {
    return $item % 2 === 0;
});
// returns [2, 4, 6]

By default, this will only pass the value to the callback. You can pass true as the second parameter to pass both the value and the key to the callback.

$collection = new Collection(['foo' => 1, 'bar' => 2, 'baz' => 3]);
return $collection->filter(function($value, $key) {
    if ($key === 'bar') {
        return $value;
    }
}, true);
// returns 2

find()

Returns the first item in the collection that satisfies the give callback.

$collection = new Collection(['foo' => 1, 'bar' => 2, 'baz' => 2]);
return $collection->find(function($item, $key) {
    return $item >= 2;
});
// returns 2

findIndex()

Like find() except it returns the index of the first item that satisfies the callback.

$collection = new Collection(['foo' => 1, 'bar' => 2, 'baz' => 3]);
return $collection->findIndex(function($item, $key) {
    return $item > 2;
});
// returns 3

flatten()

Returns a new collection that is a flattened version of the original collection. If $depth is provided, it will only flatten that many levels. By default, it will flatten only 1 level deep.

$collection = new Collection([
    'fruits' => ['apple', 'banana', 'orange'],
    'vegetables' => ['carrot', 'tomato', 'cucumber'],
]);
return $collection->flatten();
// returns ['apple', 'banana', 'orange', 'carrot', 'tomato', 'cucumber']

Keys for the flattened arrays are NOT preserved.

$collection = new Collection([
    'a' => 1,
    'b' => 2,
    'c' => 3,
    'd' => [
        'e' => 4,
        'f' => 5,
        'g' => [
            'h' => 6,
            'i' => 7,
        ],
    ],
]);
return $collection->flatten();
// returns [1, 2, 3, 4, 5, ['h' => 6, 'i' => 7]]

groupBy()

Returns a new collection with the items grouped by the given key.

$collection = new Collection([
    ['name' => 'John', 'age' => 21],
    ['name' => 'Jane', 'age' => 21],
    ['name' => 'Bob', 'age' => 22],
    ['name' => 'Mary', 'age' => 22],
]);
return $collection->groupBy('age');
// returns [
//     21 => [
//         ['name' => 'John', 'age' => 21],
//         ['name' => 'Jane', 'age' => 21],
//     ],
//     22 => [
//         ['name' => 'Bob', 'age' => 22],
//         ['name' => 'Mary', 'age' => 22],
//     ],
// ]

includes()

Returns boolean true if the collection contains the given value, false otherwise.

$collection = new Collection(['foo', 'bar', 'baz']);
return $collection->includes('bar');
// returns true

isEmpty()

Returns boolean true if the collection is empty, false otherwise.

$collection = new Collection(['foo', 'bar', 'baz']);
return $collection->isEmpty();
// returns false

$collection = new Collection();
return $collection->isEmpty();
// returns true

indexOf()

Returns the index of the given value, or -1 if it is not found.

$collection = new Collection(['foo', 'bar', 'baz']);
return $collection->indexOf('bar');
// returns 1

join()

Return all values joined by a given string.

$collection = new Collection(['foo', 'bar', 'baz']);
return $collection->join(', ');
// returns 'foo, bar, baz'

If a second parameter is provided, it will be used as the last separator.

$collection = new Collection(['foo', 'bar', 'baz']);
return $collection->join(', ', ' and ');
// returns 'foo, bar and baz'

key()

Returns the key of the current item of the collection.

$collection = new Collection(['foo', 'bar', 'baz']);
return $collection->key();
// returns 0

$collection = new Collection(['foo' => 10, 'bar' => 15, 'baz' => 20]);
return $collection->key();
// returns 'foo'

keys()

Returns a new collection with only the keys from the original collection.

$collection = new Collection(['foo' => 10, 'bar' => 15, 'baz' => 20]);
return $collection->keys();
// returns ['foo', 'bar', 'baz']

map()

Returns a new collection with the results of the callback applied to each item.

$collection = new Collection([1, 2, 3, 4, 5]);
return $collection->map(function($item) {
    return $item * 2;
});
// returns [2, 4, 6, 8, 10]

merge()

Merges the given array or collection with the current collection. This uses the array_merge() function, so any duplicate keys will be overwritten by the new values.

$collection = new Collection(['foo', 'bar', 'baz']);
return $collection->merge(['a', 'b', 'c']);
// returns ['foo', 'bar', 'baz', 'a', 'b', 'c']

pop()

Removes and returns the last item in the collection, shortening the items by 1. If no items are present null is returned.

NOTE: This method is NOT immutable and affects the original collection.

$collection = new Collection(['foo', 'bar', 'baz']);
return $collection->pop();
// returns 'baz'
// $collection = ['foo', 'bar']

push()

Adds one or more items to the end of the collection.

$collection = new Collection(['foo', 'bar', 'baz']);
return $collection->push('a', 'b', 'c');
// returns ['foo', 'bar', 'baz', 'a', 'b', 'c']

reduce()

Returns the value created when the callback is applied to each item in the collection, passing the result into the next callback, and so on.

$collection = new Collection([1, 2, 3, 4, 5]);
return $collection->reduce(function($carry, $item) {
    return $carry + $item;
});
// returns 15

reverse()

Returns a new collection with the items in reverse order.

$collection = new Collection(['foo', 'bar', 'baz']);
return $collection->reverse();
// returns ['baz', 'bar', 'foo']

shift()

Removes and returns the first item in the collection, shortening the items by 1. If no items are present null is returned.

NOTE: This method is NOT immutable and affects the original collection.

$collection = new Collection(['foo', 'bar', 'baz']);
return $collection->shift();
// returns 'foo'
// $collection = ['bar', 'baz']

slice()

Returns a new collection with only the items between and including the given start and end indexes. If no end index is provided, it will return all items from the start index to the end of the collection.

$collection = new Collection(['foo', 'bar', 'baz', 'a', 'b', 'c']);
return $collection->slice(2, 4);
// returns ['baz', 'a', 'b']

sort()

Returns a new collection with the items sorted in ascending order by the given callback. If no callback is provided, it will sort the items alphabetically.

$collection = new Collection(['foo', 'bar', 'baz']);
return $collection->sort();
// returns ['bar', 'baz', 'foo']

$collection = new Collection(['foo', 'bar', 'baz']);
return $collection->sort(function($a, $b) {
    return $a <=> $b;
});
// returns ['bar', 'baz', 'foo']

sortDesc()

Returns a new collection with the items sorted in descending order by the given callback. If no callback is provided, it will attempt sort the items alphabetically.

$collection = new Collection(['foo', 'bar', 'baz']);
return $collection->sortDesc();
// returns ['foo', 'baz', 'bar']

$collection = new Collection(['foo', 'bar', 'baz']);
return $collection->sortDesc(function($a, $b) {
    return $a <=> $b;
});
// returns ['foo', 'baz', 'bar']

splice()

Returns a new collection with the portion of the items of the collection either removed or replaced with a new item(s).

NOTE: This method is NOT idempotent and affects the original collection.

$collection = new Collection(['red', 'green', 'yellow', 'blue']);
$new = $collection->splice(2);
// $new = ['yellow', 'blue']
// $collection = ['red', 'green']

You can also replace the removed items with new items. The second parameter is the number of items to remove. The third parameter is an array of items to insert into the original collection.

$collection = new Collection(['red', 'green', 'yellow', 'blue']);
$new = $collection->splice(2, 1, 'orange');
// $new = ['yellow']
// $collection = ['red', 'green', 'orange', 'blue']

sum($key)

Returns the sum of all items in the collection. If $key is provided, it will return the sum of $key within each item.

$collection = new Collection([1, 2, 3, 4, 5]);
return $collection->sum();
// returns 15
$collection = new Collection([
    ['foo' => 10],
    ['foo' => 20],
    ['foo' => 30],
    ['foo' => 40],
]);
return $collection->sum('foo');
// returns 100

take()

Returns a collection with the first or last items based on $limit.

$collection = new Collection([1, 2, 3, 4, 5]);
return $collection->take(2);
// returns [1, 2]

You can also use negative number, to get items from the end of collection.

$collection = new Collection([1, 2, 3, 4, 5]);
return $collection->take(-2);
// returns [4, 5]

To preverse keys, you can use the second parameter:

$collection = new Collection([1, 2, 3, 4, 5]);
return $collection->take(-2, true);
// returns [3 => 4, 4 => 5]

unique()

Returns a new collection with only unique items from the original collection.

$collection = new Collection([1, 2, 2, 3, 1, 5, 1, 3]);
return $collection->unique();
// returns [0 => 1, 1 => 2, 3 => 3, 5 => 5]

You can also pass the column name as a string or multiple columns as array as parameter if you work with associative arrays or objects.

$collection = new Collection([
    ['id' => 1, 'name' => 'John'],
    ['id' => 2, 'name' => 'Jane'],
    ['id' => 1, 'name' => 'Jim'],
    ['id' => 3, 'name' => 'Joe'],
]);
return $collection->unique('id');
// returns [
//    0 => ['id' => 1, 'name' => 'John'],
//    1 => ['id' => 2, 'name' => 'Jane'],
//    3 => ['id' => 3, 'name' => 'Joe'],
//]

values()

Returns a new collection with only the values from the original collection.

$collection = new Collection([
    'foo' => 10,
    'bar' => 15,
    'baz' => 20
]);
return $collection->values();
// returns [10, 15, 20]

valid()

Returns boolean true if the current item is valid (has a key), false otherwise.

$collection = new Collection(['foo', 'bar', 'baz']);
return $collection->valid();
// returns true

when($callback)

Returns the result of the callback if the collection is not empty. If the collection is empty, it will return the collection.

$collection = new Collection([
    'a' => 1,
    'b' => 2,
    'c' => 3,
    'd' => 4,
    'e' => 5,
]);
$new = $collection->when(function ($item) {
    return $item % 2 === 0;
});
// returns ['b' => 2, 'd' => 4]

unless($callback)

Returns a new collection that contains all items where the callback evaluates to false.

$collection = new Collection([
    'a' => 1,
    'b' => 2,
    'c' => 3,
    'd' => 4,
    'e' => 5,
]);
$new = $collection->unless(function ($item) {
    return $item % 2 === 0;
});
// returns ['a' => 1, 'c' => 3, 'e' => 5]