Appending or merging is a common array operation. And since arrays are used everywhere in PHP, you cannot afford not to know how to do it properly. But why would it be so hard?
There are two options to append or merge arrays in PHP: the
+
operator and thearray_merge
function. It's not always clear, which one to use.Arrays in PHP are actually ordered maps. We use and think about them as normal arrays and associative arrays. But since the underlying structure is the same, some results might surprise you.
The differences are subtle and I often forget them. This is why created this post.
TL;DR, here are the key takeaways as a cheat sheet:
$left + $right |
array_merge($left, $right) |
|
---|---|---|
Key types matter | No | Yes |
If numeric key matches | Left-hand value is used | Appended |
If string key matches | Left-hand value is used | Right-hand value is used |
Renumbers result keys | No | Yes |
But for those of you who are interested in the details, let's dive right into it.
Option 1: The +
Operator
The +
operator, applied to arrays is also called the union operator. When computing $a + $b
, $b
is appended to $a
. But if a key occurs in both arrays, only the value from the left-hand side is used.
The type of the keys is ignored: numeric and string keys are treated the same way and the keys are always preserved.
đ The +
operator is more intuitive for arrays with explicit keys.
Option 2: The array_merge
Function
The built-in function array_merge
is similar, but a bit more intricate. Again, array_merge($a, $b)
appends $b
to $a
.
If a string key occurs in both arrays, the value from the right-hand side is used.
But if a numeric key matches, the corresponding value from the right-hand side is appended. Because this behavior cannot preserve the keys, the resulting numeric keys are renumbered.
đ As we'll see, this makes array_merge
more geared towards handling "normal" arrays.
Use Case 1: Normal Arrays
What are "normal" arrays in PHP? They are arrays with numeric keys, starting at zero: ['x1', 'y1']
is a shortcut for [0 => 'x1', 1 => 'y2']
.
Let's see how the +
operator and array_merge
perform on "normal" arrays:
$a = ['x1', 'y1']; // == [0 => 'x1', 1 => 'y1']
$b = ['y2', 'z2']; // == [0 => 'y2', 1 => 'z2']
$a + $b == ['x1', 'y1']; // == [0 => 'x1', 1 => 'y1']
array_merge($a, $b) == ['x1', 'y1', 'y2', 'z2'];
â ī¸ Because the implicit keys match, the
+
operator only uses the values from the left-hand side.array_merge
appends values for numeric keys: we get what we expect from an "append" function.
đ To append two "normal" arrays, use array_merge
.
Use Case 2: Numeric Keys
But what happens if we use numeric keys, which do not start at zero?
$a = [1 => 'x1', 2 => 'y1'];
$b = [2 => 'y2', 3 => 'z2'];
$a + $b == [1 => 'x1', 2 => 'y1', 3 => 'z2'];
array_merge($a, $b) == ['x1', 'y1', 'y2', 'z2'];
// == [0 => 'x1', 1 => 'y1', 2 => 'y2', 3 => 'z2']
The
+
operator's result is consistent with what we learned previously. When a key matches, the value from$a
has priority.At a first glance, the result of
array_merge
looks similar like before, but notice that the keys changed.array_merge
actually renumbers the numeric keys, starting at zero.
â ī¸ If you need to preserve numeric keys, array_merge
will not work.
Use Case 3: String Keys
Let's move on and see how +
and array_merge
handle arrays with string keys.
$a = ['a' => 'x1', 'b' => 'y1'];
$b = ['b' => 'y2', 'c' => 'z2'];
$a + $b == ['a' => 'x1', 'b' => 'y1', 'c' => 'z2'];
array_merge($a, $b) == ['a' => 'x1', 'b' => 'y2', 'c' => 'z2'];
The
+
operator handles string keys the same way, it handled numeric keys: when a key matches, the value from$a
is taken.Now,
array_merge
behaves differently: when a string key matches, the value from$b
is taken.
âšī¸ For matching string keys, +
takes the value from the left-hand side, array_merge
takes the value from the right-hand side.
Use Case 4: Mixed Key Types
Arrays with mixed key types do not change anything about the rules explained above. The merging procedure applies the rules key by key. Here you can see all the rules in action:
$a = ['a' => 'x1', 'b' => 'y1', 'z1', 5 => '1st'];
$b = ['b' => 'x2', 'c' => 'y2', 'z2', 5 => '2nd'];
$a+$b == [
'a' => 'x1', // key only in $a
'b' => 'y1', // matching string key -> value from $a
0 => 'z1', // matching implicit numeric key -> value from $a
5 => '1st', // matching numeric key -> value from $a
'c' => 'y2', // key only in $b
];
array_merge($a, $b) == [
'a' => 'x1', // key only in $a
'b' => 'x2', // matching string key -> value from $b
0 => 'z1', // numeric key -> append and renumber
1 => '1st', // numeric key -> append and renumber
'c' => 'y2', // key only in $b
2 => 'z2', // numeric key -> append and renumber
3 => '2nd', // numeric key -> append and renumber
];
Edge Case: Null Values
Finally, let's see what happens when one of the arrays is null
. It depends on the PHP version:
-
PHP 8.0 throws a
TypeError
when passingnull
to the+
operator orarray_merge
. -
PHP 7.4 also produces a fatal error, when using
null
as an operand on the+
operator. But when usingnull
as an argument inarray_merge
, PHP 7.4 only produces a warning and returnsnull
.
In my opinion, generating a type error or warning is not acceptable. I strongly suggest you never use the +
operator or array_merge
on null
values.
⥠Ensure that none of the arrays are null
.
Top comments (2)
have you tried this?
Thanks for your feedback. đ You are absolutely right. The spread operator is a more readable alternative for
array_merge
, if you are working with array literals.â ī¸ In all current PHP versions (up to 8.0) the spread operator does not work for arrays with string keys.
But that will change in PHP 8.1 . đđđ
Then it's effectively an
array_merge
alternative for array literals.