202
$test = array('hi');
$test += array('test','oh');
var_dump($test);

What does + mean for array in PHP?

user198729
  • 55,886
  • 102
  • 239
  • 342
  • 5
    I notice your question had `+=` and the accepted answer had `+`. From my testing they seem to behave the same. – user151841 Aug 24 '12 at 17:24
  • 7
    The [documentation](http://php.net/manual/en/language.operators.array.php) sums it up pretty well – artfulrobot Aug 22 '13 at 13:53
  • 1
    possible duplicate of [Reference - What does this symbol mean in PHP?](http://stackoverflow.com/questions/3737139/reference-what-does-this-symbol-mean-in-php) – scrowler Jun 26 '14 at 03:40
  • @RobbieAverill - this is the question that that Reference question refers to. So if anything that Reference question is the duplicate – icc97 Nov 21 '16 at 12:29
  • 2
    Is anyone else slightly horrified that such a fundamental thing as array concatenation has to be done through `array_merge`? It's as if arrays are by default associative arrays and numeric arrays are second class citizens. – icc97 Nov 21 '16 at 12:35
  • (First comment of the documentation)[http://php.net/manual/en/language.operators.array.php#86379] is as good as any of these answers. – icc97 Nov 21 '16 at 12:53

8 Answers8

282

Quoting from the PHP Manual on Language Operators

The + operator returns the right-hand array appended to the left-hand array; for keys that exist in both arrays, the elements from the left-hand array will be used, and the matching elements from the right-hand array will be ignored.

So if you do

$array1 = ['one',   'two',          'foo' => 'bar'];
$array2 = ['three', 'four', 'five', 'foo' => 'baz']; 

print_r($array1 + $array2);

You will get

Array
(
    [0] => one   // preserved from $array1 (left-hand array)
    [1] => two   // preserved from $array1 (left-hand array)
    [foo] => bar // preserved from $array1 (left-hand array)
    [2] => five  // added from $array2 (right-hand array)
)

So the logic of + is equivalent to the following snippet:

$union = $array1;

foreach ($array2 as $key => $value) {
    if (false === array_key_exists($key, $union)) {
        $union[$key] = $value;
    }
}

If you are interested in the details of the C-level implementation head to


Note, that + is different from how array_merge() would combine the arrays:

print_r(array_merge($array1, $array2));

would give you

Array
(
    [0] => one   // preserved from $array1
    [1] => two   // preserved from $array1
    [foo] => baz // overwritten from $array2
    [2] => three // appended from $array2
    [3] => four  // appended from $array2
    [4] => five  // appended from $array2
)

See linked pages for more examples.

simhumileco
  • 21,911
  • 14
  • 106
  • 90
Gordon
  • 296,205
  • 68
  • 508
  • 534
  • Is the order of keys after `+` operation guaranteed by the **specs**? – Pacerier Mar 30 '15 at 12:48
  • 1
    @Pacerier PHP produced by php.net doesn't have a formal spec, but both the `+` and `array_merge` call `zend_hash_merge` under the hood. This is also expected, since in PHP arrays are implemented as ordered hash maps. – bishop May 19 '15 at 18:34
  • 1
    @Pacerier The php.net online docs are the closest record to a specification, but IMO those docs fall way short of a true spec: one, they're updated after the code is written; two, they're not written to cover every special usage. – bishop May 25 '15 at 00:44
  • @bishop, It has been over 20 years, Has no one stepped forward with a proposal of a real specs then? – Pacerier May 26 '15 at 03:15
  • @Pacerier To clarify Gordon's link, that specification is for HHVM. While HHVM "deliberately recreates PHP.net bugs and oddities", it should be not be considered a formal specification for PHP as published by PHP.net. – bishop May 26 '15 at 13:28
  • @Pacerier Stas has completed a working draft spec for [PHP 5.6](https://github.com/php/php-langspec/blob/PHP-5.6/spec/00-specification-for-php.md), however it doesn't appear to address this question. I'll raise it for clarification. – bishop Jun 30 '15 at 19:55
  • @bishop, The question is whether Zend will surrender PHP to Facebook. Facebook could simply purchase `php.net` from Zend. Also, by "Stas" you are talking about "Stas Malyshev"? – Pacerier Jul 02 '15 at 07:53
  • 19
    The behaviour of PHP's `+` and `array_merge` is perverse and unintuitive. They're the opposite way round from what a plain-English reading would intuitively tell you 'adding' or 'merging' arrays would do. Other languages/libraries use `+` to concatenate lists (e.g. in Python) and "merge" functions to add the key/value pairs from one object onto another (e.g. in lodash). Yet in PHP it's the other way round; `array_merge` can be used for concatenating list-like arrays but `+` cannot. Unlike `array_merge`, `+` always performs the operation that would be called a "merge" in any other language. – Mark Amery Aug 11 '15 at 11:18
  • @MarkAmery definitely agree, it seems like numeric arrays are second class citizens to associative arrays, or possibly they just are associative arrays with numeric keys under the hood. I think there could just be a `array_concat` method as an alias for `array_merge`. This would be consistent with Python as [dict concatenation is treated the same as merging them](http://stackoverflow.com/questions/1781571/how-to-concatenate-two-dictionaries-to-create-a-new-one-in-python#1784128). – icc97 Nov 21 '16 at 13:19
  • 1
    @icc97 they are indeed only HashMaps. See https://nikic.github.io/2014/12/22/PHPs-new-hashtable-implementation.html – Gordon Nov 21 '16 at 13:33
  • 2
    I've tried [submitting a bug](https://bugs.php.net/bug.php?id=73576) to see if an alias `array_concat` could be created for `array_merge`. – icc97 Nov 21 '16 at 22:04
19

The best example I found for using this is in a config array.

$user_vars = array("username"=>"John Doe");
$default_vars = array("username"=>"Unknown", "email"=>"no-reply@domain.com");

$config = $user_vars + $default_vars;

The $default_vars, as it suggests, is the array for default values. The $user_vars array will overwrite the values defined in $default_vars. Any missing values in $user_vars are now the defaults vars from $default_vars.

This would print_r as:

Array(2){
    "username" => "John Doe",
    "email" => "no-reply@domain.com"
}

I hope this helps!

James
  • 5,016
  • 4
  • 37
  • 76
Frank de Jonge
  • 1,406
  • 12
  • 21
6

This operator takes the union of two arrays (same as array_merge, except that with array_merge duplicate keys are overwritten).

The documentation for array operators is found here.

Peter Smit
  • 24,538
  • 27
  • 105
  • 165
  • 1
    A word of caution for beginners here, the result of the operation is **null** if any one of the arrays is **null**. Some might not care about this assuming since it is a union operation, the result will be the proper (not-null) array if one of them is null. But, that holds true if one of the arrays is an **empty** array. – Sandeepan Nath Jul 13 '12 at 06:52
  • So, as a good practice, I think, we should initialize the input arrays as empty arrays. What do you guys say? – Sandeepan Nath Jul 13 '12 at 06:58
5

Carefull with numeric keys, if they should be preserved or if you don't want to loose anything

$a = array(2 => "a2", 4 => "a4", 5 => "a5");
$b = array(1 => "b1", 3 => "b3", 4 => "b4");

union

print_r($a+$b);
Array
(
    [2] => a2
    [4] => a4
    [5] => a5
    [1] => b1
    [3] => b3
)

merge

print_r(array_merge($a, $b));
Array
(
    [0] => a2
    [1] => a4
    [2] => a5
    [3] => b1
    [4] => b3
    [5] => b4
)
dcaillibaud
  • 311
  • 2
  • 5
3

The + operator produces the same results as array_replace(). However since the operator arguments are reversed, the ordering of the resulting array may also be different.

Expanding on another example from this page:

$array1 = array('one', 'two', 'foo' => 'bar');
$array2 = array('three', 'four', 'five', 'foo' => 'baz'); 

print_r($array1 + $array2);
print_r(array_replace($array2, $array1)); //note reversed argument order

outputs:

Array
(
    [0] => one   // preserved from $array1
    [1] => two   // preserved from $array1
    [foo] => bar // preserved from $array1
    [2] => five  // added from $array2
)
Array
(
    [0] => one   // preserved from $array1
    [1] => two   // preserved from $array1
    [2] => five  // added from $array2
    [foo] => bar // preserved from $array1
)
Tamlyn
  • 18,041
  • 10
  • 96
  • 117
1
  1. Array plus operation treats all array as assoc array.
  2. When key conflict during plus, left(previous) value will be kept

I post the code below to make things clear.

$a + $b = array_plus($a, $b)

function array_plus($a, $b){
    $results = array();
    foreach($a as $k=>$v) if(!isset($results[$k]))$results[$k] = $v;
    foreach($b as $k=>$v) if(!isset($results[$k]))$results[$k] = $v;
    return $results;
}
Gucci Koo
  • 481
  • 4
  • 10
-2

It will append the new array to the previous.

SorcyCat
  • 1,200
  • 9
  • 19
-4
$var1 = "example";
$var2 = "test";
$output = array_merge((array)$var1,(array)$var2);
print_r($output);

Array ( [0] => example [1] => test )

Henning
  • 9
  • 1