Correctly merging two arrays into a single array requires thinking about the type of data we have. Is our data flat or does it contain nested arrays? What should happen when both arrays contain the same key?
PHP provides three ways to merge arrays.
- The array union operator: +.
- The array_merge function.
- The array_merge_recursive function.
We may also need Zend\Stdlib\ArrayUtils::merge which ships as part of Zend Framework 2 and can be included in our application by requiring
zendframework/zend-stdlib with Composer.
Choosing the right function
When our data is flat we can use
array_merge or the
+ operator. When we want to merge nested arrays we must use a recursive function like
Duplicates occur when both input arrays contain the same key. Only keys are considered when determining duplicates, not values. Duplicates create a merge conflict that is resolved by either appending or replacing duplicate key values.
+ operator behaves consistently (it always replaces duplicates); the other merge functions change behaviour depending on whether the key type is numeric or a string as shown below. However,
ArrayUtils::merge will behave consistently when
true is passed as the third parameter since Zend Framework 2.2.6.
With the exception of the
+ operator, values in numeric keys are appended and reindexed. The
+ operator always replaces duplicate keys regardless of the type.
|ArrayUtils::merge(x, y, true)|
In these examples both arrays have the same implicit numeric key (0). The
+ operator drops duplicates found in the right operand.
 + ;
[0 => 1]
The merge functions append values and reindex keys. Since the input arrays are flat in these examples, the result is the same for the recursive functions.
[0 => 1, 1 => 2]
With the exception of
array_merge_recursive, values in duplicate string keys are replaced. However,
array_merge_recursive always appends duplicate keys regardless of the type.
Like numeric keys, the
+ operator always drops duplicates found in the right operand.
['foo' => 1] + ['foo' => 2];
['foo' => 1]
For string keys,
array_merge drops duplicates found in the first argument.
array_merge(['foo' => 1], ['foo' => 2]);
['foo' => 2]
array_merge_recursive preserves duplicates by pushing each value into a new array under the duplicate key.
array_merge_recursive(['foo' => 1], ['foo' => 2]);
['foo' => [0 => 1, 1 => 2]]
The argument for which duplicate keys are kept is said to have precedence during a merge. Argument order determines which values are kept and which are lost during replacement.
+ operator gives precedence to the first operand but the other merge functions give precedence to the second argument as shown in the table below. Argument order for
array_merge_recursive is usually irrelevant since it always appends duplicates.
|Function or operator||Precedence|
To merge two arrays correctly we must consider the data structure of each array and how we want to handle conflicts that occur when both arrays contain the same key. Once we know the data structure and have chosen a duplicate handling strategy we can select the correct function to merge our arrays.
Finally we ensure our arguments are specified in the correct order to give precedence to the array whose data we wish to keep when conflicts occur.