cocur/chain

Consistent and chainable array manipulation

v0.3 2017-09-07 15:34 UTC

README

Chain provides you with a consistent and chainable way to work with arrays in PHP.

Build Status Windows Build status Scrutinizer Code Quality Code Coverage StyleCI

Made by Florian Eckerstorfer in Vienna, Europe.

Motivation

Let us be honest. Working with arrays in PHP is a mess. First of all, you have to prefix most (but not all) functions with array_, the parameter ordering is not consistent. For example, array_map() expects the callback as first parameter and the array as the second, but array_filter() expects the array as first and the callback as second. You also have to wrap the function calls around the array, the resulting code is not nice to look at, not readable and hard to understand.

$arr = array_filter(
    array_map(
        function ($v) { return rand(0, $v); },
        array_fill(0, 10, 20)
    ),
    function ($v) { return $v & 1; }
);

Chain wraps the array in an object and gives you a chainable interface.

$chain = Chain::fill(0, 10, 20)
    ->map(function ($v) { return rand(0, $v); })
    ->filter(function ($v) { return $v & 1; });

Take a look at the following code. How long do you need to understand it?

echo array_sum(array_intersect(
    array_diff([1, 2, 3, 4, 5], [0, 1, 9]),
    array_filter([2, 3, 4], function ($v) { return !($v & 1); })
));

What about this?

echo Chain::create([1, 2, 3, 4, 5])
    ->diff([0, 1, 9])
    ->intersect(Chain::create([2, 3, 4])->filter(function ($v) { return !($v & 1); }))
    ->sum();

Hint: It takes the diff of two arrays, intersects it with a filtered array and sums it up.

Installation

You can install Chain using Composer:

$ composer require cocur/chain

Usage

Chain allows you to create, manipulate and access arrays.

Array Creation

You can create a Chain by passing an array to the constructor.

$chain = new Chain([1, 2, 3]);

Or with a convenient static method:

$chain = Chain::create([1, 2, 3]);

In addition a Chain can also be created by the static fill() method, which is a wrapper for the array_fill() function.

$chain = Chain::fill(0, 10, 'foo');

There is also a method, ::createFromString(), that creates the Chain from a string. In addition to the string you need to provide a delimiter, which is used to split the string. If the option regexp is passed in the delimiter must be a regular expression.

Chain::createFromString(',', '1,2,3')->array;                               // -> [1, 2, 3]
Chain::createFromString('/,|.|;/', '1,2.3;4,5', ['regexp' => true])->array; // -> [1, 2, 3, 4, 5]

Array Manipulation

Chains manipulation methods manipulate the underlying array and return the object, that is, they can be chained. Most of the methods are simple wrappers around the corresponding array_ function.

In the following example ->map() is used to multiply each element by 3 and then filter the array to only contain odd elements.

$chain = (new Chain([1, 2, 3]))
    ->map(function ($v) { return $v*3; })
    ->filter(function ($v) { return $v & 1; });
$chain->array; // -> [3, 9]

When a method accepts an array (->diff() or ->intersect()) you can also pass in another instance of Chain instead of the array.

List of Array Manipulation Methods

All of these methods manipulate the array, but not all of them return an instance of Cocur\Chain\Chain. For example, ->shift() removes the first element from the array and returns it.

  • ->changeKeyCase()
  • ->combine(array|Chain, array|Chain)
  • ->count()
  • ->diff(array|Chain)
  • ->filter(callable)
  • ->flip()
  • ->intersect(array|Chain)
  • ->intersectAssoc(array|Chain)
  • ->intersectKey(array|Chain)
  • ->map(callable)
  • ->merge(array|Chain)
  • ->pad(int, mixed)
  • ->pop()
  • ->product()
  • ->push(mixed)
  • ->reduce(callable[, int])
  • ->reverse([bool])
  • ->shift()
  • ->shuffle()
  • ->sort(sortFlags)
  • ->sortKeys(sortFlags)
  • ->splice(offset[, length[, replacement]])
  • ->sum()
  • ->unique()
  • ->unshift(mixed)

Array Access

Most importantly you can access the underlying array using the public array property.

$chain = new Chain([1, 2, 3]);
$chain->array; // -> [1, 2, 3]

Chain implements the Traversable interface.

$chain = new Chain([1, 2, 3]);
foreach ($chain as $key => $value) {
  // ...
}

It also implements the ArrayAccess interface allowing to access elements just like in any normal array.

$chain = new Chain();
$chain['foo'] = 'bar';
if (isset($chain['foo'])) {
    echo $chain['foo'];
    unset($chain['foo']);
}

Additionally Chain contains a number of methods to access properties of the array. In contrast to the manipulation methods these methods return a value instead of a reference to the Chain object. That is, array access methods are not chainable.

$chain = new Chain([1, 2, 3]);
$chain->count(); // -> 3
$chain->sum();   // -> 6
$chain->first(); // -> 1
$chain->last();  // -> 3

$chain->reduce(function ($current, $value) {
    return $current * $value;
}, 1); // -> 6

List of Array Access Methods

  • ->count()
  • ->countValues()
  • ->first()
  • ->last()
  • ->reduce()
  • ->sum()

Author

Chain has been developed by Florian Eckerstorfer (Twitter) in Vienna, Europe.

Chain is a project of Cocur. You can contact us on Twitter: @cocurco

Support

If you need support you can ask on Twitter (well, only if your question is short) or you can join our chat on Gitter.

Gitter

In case you want to support the development of Chain you can send me an Euro or two.

Change Log

Version 0.3 (7 September 2017)

  • #12 Restore constructor (by sanmai)
  • Move first() and last() methods into traits
  • Add additional links (CountValues, KeyExists, Splice)
  • Update Merge link

Version 0.2 (6 November 2015)

  • #11 Add Cocur\Chain\Chain::createFromString() to create a chain from a string
  • #10 Add methods to Cocur\Chain\AbstractChain to retrieve first and last element of chain.
  • #9 Cocur\Chain\Chain is now countable

Version 0.1 (6 November 2015)

  • Initial release

License

The MIT license applies to Chain. For the full copyright and license information, please view the LICENSE file distributed with this source code.