How to Append Arrays in PHP: + vs. array_merge
Tags: php, webdev, cheatsheet, beginners
Published: 2021-10-05 12:11:37

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 the `array_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](https://www.php.net/manual/en/language.operators.array.php). 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`](https://www.php.net/manual/en/function.array-merge.php) 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:

```php
$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**?

```php
$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.

```php
$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:

```php
$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 passing `null` to the `+` operator or `array_merge`.
- **PHP 7.4** also produces a fatal error, when using `null` as an operand on the `+` operator. But when using `null` as an argument  in `array_merge`, PHP 7.4 only produces a warning and returns `null`.

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`.