DEV Community

Cover image for PHP Collections: Array to Map
toco
toco

Posted on • Edited on • Originally published at aimeos.org

PHP Collections: Array to Map

Arrays are the working horse of PHP, the programming language used by the vast majority of web applications. An array seems to be incredible simple to use but things get complicated and ugly when PHP functions for array manipulation come into play. Are you tired of hard to read code with excessive error handling too? Then collections can be the answer.

Why?

Here’s a common example of how array manipulation is done in most PHP code:

$list = [
    ['id' => 'one', 'value' => 'value1'],
    ['id' => 'two', 'value' => 'value2'],
    null
];

$list[] = ['id' => 'three', 'value' => 'value3'];    // add element
unset( $list[0] );                                   // remove element
$list = array_filter( $list );                       // remove empty values
sort( $list );                                       // sort elements
$pairs = array_column( $list, 'value', 'id' );       // create ['three' => 'value3']
$value = reset( $pairs ) ?: null;                    // return first value
Enter fullscreen mode Exit fullscreen mode

It adds/removes elements, sorts and transforms the content and retrieves the first element. You can’t write that shorter or more elegant and moreover, you need to check almost all array functions for errors.

Using maps

The map composer package offers an easy API comparable to jQuery or Laravel collections:

composer req aimeos/map
Enter fullscreen mode Exit fullscreen mode

When using the Map object, you can do the same as above more elegant with less code:

$list = [
    ['id' => 'one', 'value' => 'value1'],
    ['id' => 'two', 'value' => 'value2'],
    null
];

$value = map( $list )                                // create Map
    ->push( ['id' => 'three', 'value' => 'value3'] ) // add element
    ->remove( 0 )                                    // remove element
    ->filter()                                       // remove empty values
    ->sort()                                         // sort elements
    ->col( 'value', 'id' )                           // create ['three' => 'value3']
    ->first();                                       // return first value
Enter fullscreen mode Exit fullscreen mode

And contrary to PHP arrays, you don’t have to care about error handling because either, there are no errors possible or the Map object will throw an exception if something is really wrong.

Of course, you can use the Map object still like a plain PHP array:

$map[] = ['id' => 'three', 'value' => 'value3'];
$value = $map[0];
count( $map );
foreach( $map as $key => value );
Enter fullscreen mode Exit fullscreen mode

In addition, Map objects allow you to pass anonymous functions to a lot of methods. Thus, you can process and transform the elements according to your current needs, e.g. using the each() method:

$map->each( function( $val, $key ) {
    echo $key . ': ' . $val;
} );
Enter fullscreen mode Exit fullscreen mode

You can even extend Maps dynamically by own methods. This is especially useful if you need a transformation of the Map elements more often and at several places of your code:

Map::method( 'strrev', function( $sep ) {
    return strrev( join( '-', $this->items ) );
} );
Map::from( ['a', 'b'] )->strrev( '-' );
Enter fullscreen mode Exit fullscreen mode

The best part is using a Map like a jQuery object, where methods are applied to all objects of the Map. Then, you can create expressive code in one line:

class MyClass {
    private $code;
    private $status;

    public function __construct( $code ) { $this->code = $code; }
    public function setStatus( $s ) { $this->stat = $s; return $this; }
    public function getCode() { return $this->code; }
}

$objects = Map::from( ['a' => new MyClass( 'x' ), 'b' => new MyClass( 'y' )] );
$result = $objects->setStatus( 1 )->getCode()->toArray();
Enter fullscreen mode Exit fullscreen mode

The example will call setStatus(1) on all objects and creates a new Map with the returned values. Because setStatus() returns the same object ($this), we can apply another method on all objects afterwards (getCode()). The results of getCode() is wrapped in a Map object again and toArray() returns a plain PHP array which consists of:

['a' => 'x', 'b' => 'y']
Enter fullscreen mode Exit fullscreen mode

Available methods

The Map object contains methods for almost all array functions available and more like collapse(), flat(), toJson() or methods found in the Javascript Array prototype. Here’s a list of its methods and for documentation, have a look at the Map readme at GitHub where you can also check the code.

function map() : Creates a new map from elements
arsort() : Reverse sort elements with keys
asort() : Sort elements with keys
chunk() : Splits the map into chunks
clear() : Removes all elements
col() : Creates a key/value mapping
collapse() : Collapses multi-dimensional elements
concat() : Combines the elements
copy() : Creates a new copy
count() : Returns the number of elements
diff() : Returns the missing elements
diffAssoc() : Returns the missing elements and checks keys
diffKeys() : Returns the missing elements by keys
each() : Applies a callback to each element
empty() : Tests if map is empty
equals() : Tests if map contents are equal
filter() : Applies a filter to the map elements
find() : Returns the first matching element
first() : Returns the first element
flip() : Exchanges keys with their values
flat() : Flattens multi-dimensional elements
from() : Creates a new map from passed elements
get() : Returns an element by key
has() : Tests if a key exists
in() : Tests if element is included
includes() : Tests if element is included
intersect() : Returns the shared elements
intersectAssoc() : Returns the shared elements and checks keys
intersectKeys() : Returns the shared elements by keys
isEmpty() : Tests if map is empty
join() : Returns concatenated elements as string
keys() : Returns the keys
krsort() : Reverse sort elements by keys
ksort() : Sort elements by keys
last() : Returns the last element
map() : Applies a callback to each element and returns the results
merge() : Combines elements overwriting existing ones
method() : Registers a custom method
pipe() : Applies a callback to the map
pop() : Returns and removes the last element
pull() : Returns and removes an element by key
push() : Adds an element to the end
random() : Returns random elements
reduce() : Computes a value for the map content
remove() : Removes an element by key
replace() : Replaces elements recursively
reverse() : Reverses the array order
rsort() : Reverse sort elements
search() : Find the key of an element
set() : Overwrites an element
shift() : Returns and removes the first element
shuffle() : Randomizes the element order
slice() : Returns a slice of the map
sort() : Sorts elements
split() : Splits a string into map elements
splice() : Replaces a slice by new elements
toArray() : Returns the plain array
toJson() : Returns the elements in JSON format
uasort() : Sorts elements with keys using callback
uksort() : Sorts elements by keys using callback
union() : Combines the element without overwriting
unique() : Returns unique elements
unshift() : Adds an element at the beginning
usort() : Sorts elements using callback
values() : Returns all elements with new keys

Again, the Map documentation offers descriptions, explains parameters/return values and has examples for each method. Some methods are even better documented than the corresponding PHP array function.

Conclusion

Map objects are an easy to use and elegant way to handle PHP arrays. After using it for a while you won’t want to remember the times before. If you’ve already worked with jQuery and like it’s simplicity, you will feel like home when using appropriate lists of objects in your application.

As the Map methods are using the native array functions or are highly optimized, it’s also save to use them in large scale applications. The documentation contains a section about the Map performance and hints to avoid performance bottlenecks.

Top comments (2)

Collapse
 
tylerjusfly profile image
Tyler • Edited

Hi, do you have any idea how to get data from this array of list and also iterate over it?

Image description

Collapse
 
shop profile image
toco

Looks like a serialized JSON string. You can use \Aimeos\Map::fromJson() to parse that and iterate over the resulting multi-dimensional collection.