Take the State of PHP 2026 Survey →

Spread Operator in Array Expression View as Markdown

Implemented (PHP 7.4)
Authors
CHU Zhaowei, jhdxr@php.net
Date
2018-10-13
Version
0.2
Source
wiki.php.net/rfc/spread_operator_for_array

Vote

Support spread operator for array definition in PHP 7.4? closed
Yes
43
No
1
44 voters
ashnazg Yes 2019-04-24 16:18
bishop Yes 2019-04-24 16:59
carusogabriel Yes 2019-04-22 23:22
colinodell Yes 2019-04-22 15:07
cpriest Yes 2019-04-29 11:02
dams Yes 2019-04-22 08:48
danack Yes 2019-04-23 10:00
didou Yes 2019-04-22 09:02
diegopires Yes 2019-04-23 12:12
duncan3dc Yes 2019-04-22 08:15
emir Yes 2019-04-22 07:56
galvao Yes 2019-04-22 00:00
guilhermeblanco Yes 2019-04-23 19:37
jasny Yes 2019-05-05 10:21
jhdxr Yes 2019-04-30 12:09
jwage Yes 2019-04-24 14:51
kalle Yes 2019-04-22 14:39
kguest Yes 2019-04-23 07:57
kinncj Yes 2019-04-22 23:27
levim Yes 2019-04-22 14:07
lstrojny Yes 2019-04-24 10:19
malukenho Yes 2019-05-01 10:06
marcio Yes 2019-04-24 17:36
mariano Yes 2019-04-22 08:31
mcmic Yes 2019-04-23 13:33
mike Yes 2019-04-25 08:17
nikic Yes 2019-04-23 10:25
ocramius Yes 2019-04-21 22:31
patrickallaert Yes 2019-05-02 22:14
petk Yes 2019-05-03 18:06
pmmaga Yes 2019-04-24 09:16
pollita Yes 2019-04-22 15:32
reywob Yes 2019-04-23 06:42
royopa Yes 2019-04-23 11:30
rtheunissen Yes 2019-04-23 06:25
salathe No 2019-04-22 08:09
santiagolizardo Yes 2019-04-30 22:43
sergey Yes 2019-04-22 07:51
svpernova09 Yes 2019-04-23 01:58
thekid Yes 2019-04-29 19:27
trowski Yes 2019-04-23 15:34
weierophinney Yes 2019-04-30 14:35
yunosh Yes 2019-04-24 08:56
zimt Yes 2019-04-29 06:44

Discussions on the mailing list

[RFC] Spread Operator in Array Expression
· 8 messages

RFC text

Copied from wiki.php.net, last synchronized Oct 13, 2026 11:51 UTC

Introduction

PHP has already supported argument unpacking (AKA spread operator) since 5.6. This RFC proposes to bring this feature to array expression.

Proposal

An array pair prefixed by ... will be expanded in places during array definition. Only arrays and objects who implement Traversable can be expanded.

For example,

$parts = ['apple', 'pear'];
$fruits = ['banana', 'orange', ...$parts, 'watermelon'];
// ['banana', 'orange', 'apple', 'pear', 'watermelon'];

It's possible to do the expansion multiple times, and unlike argument unpacking, ... can be used anywhere. It's possible to add normal elements before or after the spread operator.

Spread operator works for both array syntax(array()) and short syntax([]).

It's also possible to unpack array returned by a function immediately.

$arr1 = [1, 2, 3];
$arr2 = [...$arr1]; //[1, 2, 3]
$arr3 = [0, ...$arr1]; //[0, 1, 2, 3]
$arr4 = array(...$arr1, ...$arr2, 111); //[1, 2, 3, 1, 2, 3, 111]
$arr5 = [...$arr1, ...$arr1]; //[1, 2, 3, 1, 2, 3]
 
function getArr() {
  return ['a', 'b'];
}
$arr6 = [...getArr(), 'c']; //['a', 'b', 'c']
 
$arr7 = [...new ArrayIterator(['a', 'b', 'c'])]; //['a', 'b', 'c']
 
function arrGen() {
	for($i = 11; $i < 15; $i++) {
		yield $i;
	}
}
$arr8 = [...arrGen()]; //[11, 12, 13, 14]

String keys

In order to make the behavior consistent with argument unpacking, string keys are not supported. A recoverable error will be thrown once a string key is encountered.

By-reference passing

It's not possible to unpack an array by reference.

$arr1 = [1, 2, 3];
$arr2 = [...&$arr1]; //invalid syntax

However, if elements in the array to be unpacked are stored by reference, they will be stored by reference in the new array as well.

$one = 1;
$arr1 = [&$one, 2, 3];
$arr2 = [0, ...$arr1];
var_dump($arr2);
/*
array(4) {
  [0]=>
  int(0)
  [1]=>
  &int(1)
  [2]=>
  int(2)
  [3]=>
  int(3)
}
*/

Backward Incompatible Changes

This change should not break anything.

Q & A

Advantages over array_merge

  1. Spread operator should have a better performance than array_merge. It's because not only that spread operator is a language structure while array_merge is a function call, but also compile time optimization can be performant for constant arrays.
  2. array_merge only supports array, while spread operator also supports objects implementing Traversable.
// Before
array_merge(iterator_to_array($iter1), iterator_to_array($iter2))
 
// Or to generalize to all iterables
array_merge(
  is_array($iter1) ? $iter1 : iterator_to_array($iter1),
  is_array($iter2) ? $iter2 : iterator_to_array($iter2)
)
 
// After (handles both cases)
[ ...$iter1, ...$iter2 ]
 
//Thanks Rowan for providing this example

... should be preserved for other use (e.g. map concat)

This is kind of out of scope here to discuss other concat / merge operation. The important thing is we should make the behavior of same operator consistent and not to confuse userland developer. It's also why I changed the behavior for string keys in this revised version.

Proposed PHP Version(s)

next PHP 7.x, likely 7.4

RFC Impact

To Opcache

Some changes in opcache to support the new opcode is needed.

Vote

Voting started 2019-04-22 and ends 2019-05-06. A 2/3 majority is required.

Vote: Support spread operator for array definition in PHP 7.4? — Yes: 43 · No: 1 (closed)

Patches and Tests

WIP

https://github.com/php/php-src/pull/3640

Implementation

After the project is implemented, this section should contain

  1. the version(s) it was merged into
  2. a link to the git commit(s)
  3. a link to the PHP manual entry for the feature
  4. a link to the language specification section (if any)

References

Links to external references, discussions or RFCs

Rejected Features

Keep this updated with features that were discussed on the mail lists.