PHP: Array > Map 2.0

The new 2.0 major release of the PHP map package is available which includes new methods and support for working with multi-dimensional arrays in an easy way. Additionally, it comes with the best documentation ever so you find everything you need quickly!

Instead of applying independent PHP functions on arrays, use the PHP Map object to stream array data through several methods to transform, order and shorten its elements until the result exactly conforms to your requirements, for example:

$data = [
    ['name' => 'Tom', 'dep' => 'Dev', 'qty' => 30],
    ['name' => 'Bob', 'dep' => 'Sales', 'qty' => 50],
    ['name' => 'Joe', 'dep' => 'Dev', 'qty' => 10]
// get the person with the highest quantity in "Dev" department
$name = map( $data )
    ->groupBy( 'dep' )->only( 'Dev' )
    ->flat( 1 )->col( 'name', 'qty' )

To get the result in one statement is easier and much more elegant than the traditional way in PHP. The PHP Map object is perfectly suited to work on result sets returned by relational databases. You can transform them until you get a collection that exactly fits for your template generating the HTML for the frontend.

The PHP Map package combines the best from Laravel and CakePHP collections, jQuery, Backbone.js, and Lodash in an easy to use PHP package for every PHP application.

What’s new in PHP Map 2.0

One of the biggest new feature is the ability to pass a path of keys as parameter to several PHP Map methods to work on nested arrays directly. Instead of writing own code for diving into multi-dimensional arrays, you can now use the available methods to e.g. get a value by using:

map( ['key' => ['to' => ['value' => 'yes!']]] )
    ->get( 'key/to/value' ); // returns "yes!"

This also works for more advanced methods like col() to reindex an array by using a nested key:

$data = [
    ['name' => 'Tom', 'addr' => ['zip' => '12AB', 'city' => 'NY']],
    ['name' => 'Bob', 'addr' => ['zip' => '23WD', 'city' => 'LA']]
$map = map( $data )->col( 'name', 'addr/zip' );
// ['12AB' => 'Tom', '23WD' => 'Bob']

By default, a dot (“/”) is used as seperator between the array key names but you can change that for the current map using the sep() method:

$map = map( $data )->sep( '.' )->col( 'name', '' );

If you want to use another seperator in all new PHP Map objects (existing ones will keep their separator), you can change the delimiter globally with the delimiter() method:

Map::delimiter( ',' );

It also returns the delimiter used before if you want to revert the used delimiter later in your code.

Breaking changes in PHP Map 2.0

The new major version contains a few breaking changes to avoid potential problems that came up in the past. You won’t be affected by most of them but you should have a look to prevent unexpected behaviour.

New slash separator

The most important change affects parameter values including slashes because they are now treated as path separators for nested arrays.

$data = [
    'item/id' => 1,
    'item/code' => 'test',
    'item/name' => 'Test'
map( $data )->col( 'item/code', 'item/id' );
// 1.x
[1 => 'test']
// 2.x
// use instead
map( $data )->sep( '.' )->col( 'item/code', 'item/id' );

jQuery style method calls

You can call methods of objects in a map like this:

// MyClass implements setStatus() (returning $this) and
// getCode() (initialized by constructor)
$map = Map::from( [
    'a' => new MyClass( 'x' ),
    'b' => new MyClass( 'y' )
] );
$map->setStatus( 1 )->getCode()->toArray();

Before, the objects had been checked if they really implement the setStatus() and getCode() methods.

To avoid returning an empty map if the method name is wrong or the called method is catched by the __call() magic method, this isn’t the case any more. If the method isn’t implemented by all objects, PHP generates a fatal error now for better error tracing.

Second equals() parameter

The $assoc parameter of the equals() method to compare keys too has been removed and now, you must use the is() method instead:

// 1.x
map( ['one' => 1] )->equals( ['one' => 1], true );
// 2.x
map( ['one' => 1] )->is( ['one' => 1] );

New find() argument

The find() method now accepts a default value or exception object as second argument and the $reverse argument is at the third position now:

// 1.x
Map::from( ['a', 'c', 'e'] )->find( function( $value, $key ) {
    return $value >= 'b';
}, true );
// 2.x
Map::from( ['a', 'c', 'e'] )->find( function( $value, $key ) {
    return $value >= 'b';
}, null, true );

Semantic change in groupBy()

Before, items have been grouped by the key string itself if the key passed to groupBy() didn’t exist. To offer easier checking and sorting of the keys, an empty string is used as key now:

Map::from( [
    10 => ['aid' => 123, 'code' => 'x-abc'],
] )->groupBy( 'xid' );
// 1.x
    'xid' => [
        10 => ['aid' => 123, 'code' => 'x-abc']
// 2.x
    '' => [
        10 => ['aid' => 123, 'code' => 'x-abc']

Semantic change in offsetExists()

The offsetExists() method uses isset() instead of array_key_exists() now to be in line with typical PHP behavior. Thus, keys with NULL values are now treated differently:

$m = Map::from( ['foo' => null] );
// 1.x
isset( $m['foo'] ); // true
// 2.x
isset( $m['foo'] ); // false

Renamed split() to explode()

To avoid conflicts with the Laravel split() method and to be in line with the PHP explode() method, the static Map::split() method has been renamed to Map::explode(). Also, the argument order has changed:

// 1.x
Map::split( 'a,b,c', ',' );
// 2.x
Map::explode( ',', 'a,b,c' );