Table of Contents

PHP RFC: Square bracket syntax for array destructuring assignment

Background

The fundamental complex data type in PHP is the array. This data type is so frequently used that PHP has special syntax for handling it. This RFC focuses, in particular, on the syntax for two different array operations in PHP: construction of an array from values, and destructuring assignment from an array to variables.

Arrays can be constructed in PHP syntax using one of two syntax forms. The first of these, introduced in PHP 3, resembles a function call, where a series of comma-separated values (and optionally keys) is placed between array( and ):

<?php
 
// Creates an array containing elements with the values 1, 2 and 3, and keys numbered from zero
$array = array(1, 2, 3);
 
// Creates an array containing elements with the values 1, 2 and 3, and the keys "a", "b", "c"
$array = array("a" => 1, "b" => 2, "c" => 3);

The second syntax form, the so-called short array syntax introduced in PHP 5.4, is a more concise form that replaces array( and ) with [ and ]:

<?php
 
// Creates an array containing elements with the values 1, 2 and 3, and keys numbered from zero
$array = [1, 2, 3];
 
// Creates an array containing elements with the values 1, 2 and 3, and the keys "a", "b", "c"
$array = ["a" => 1, "b" => 2, "c" => 3];

Beyond being more concise, this second syntax has the benefit of not resembling a function call (preventing misunderstandings from new users), and being familiar to users of other languages like JavaScript, which use similar syntax for constructing arrays.

Similar to the array() syntax for constructing arrays, PHP has had a syntax form for assigning to variables from array elements (“destructuring”) since PHP 3, where a series of comma-separated variables are placed between list( and ):

<?php
 
// Assigns to $a, $b and $c the values of their respective array elements in $array with keys numbered from zero
list($a, $b, $c) = $array;

As of the upcoming PHP 7.1, there will also be a syntax form for specifying keys when destructuring:

<?php
 
// Assigns to $a, $b and $c the values of the array elements in $array with the keys "a", "b" and "c", respectively
list("a" => $a, "b" => $b, "c" => $c) = $array;

However, while array() has the more concise counterpart syntax [], there is currently no such counterpart for list().

Proposal

This RFC proposes introducing a second syntax form for destructuring assignment, where list( and ) are replaced with [ and ]:

<?php
 
// Assigns to $a, $b and $c the values of their respective array elements in $array with keys numbered from zero
[$a, $b, $c] = $array;
 
// Assigns to $a, $b and $c the values of the array elements in $array with the keys "a", "b" and "c", respectively
["a" => $a, "b" => $b, "c" => $c] = $array;

This syntax is more concise, and like the [] alternative to array(), this new syntax does not resemble a function call.

Importantly, this syntax for destructuring an array means there is now symmetry between array construction and destructuring, which should make it clearer what the function of the syntax is:

<?php
 
// The two lines in each of the following pairs are equivalent to each other
 
list($a, $b, $c) = array(1, 2, 3);
[$a, $b, $c] = [1, 2, 3];
 
list("a" => $a, "b" => $b, "c" => $c) = array("a" => 1, "b" => 2, "c" => 3);
["a" => $a, "b" => $b, "c" => $c] = ["a" => 1, "b" => 2, "c" => 3];
 
list($a, $b) = array($b, $a);
[$a, $b] = [$b, $a];

This symmetry between construction and destructuring is a feature in some other languages. The following code, for example, is valid ECMAScript 6, and would behave identically in PHP:

// Creates an array
$array = [1, 2, 3];
 
// Extracts its elements into variables
[$a, $b, $c] = $array;

Details

The list() syntax is not only permitted on the left-hand side of an assignment operation, but also as variable in a foreach loop. The new [] syntax for destructuring would likewise be permitted here:

<?php
 
foreach ($points as ["x" => $x, "y" => $y]) {
    var_dump($x, $y);
}

Both due to implementation issues, and for consistency's sake, list() cannot be nested inside [], nor vice-versa:

<?php
 
// This is not allowed:
list([$a, $b], [$c, $d]) = [[1, 2], [3, 4]];
 
// This is also not allowed:
[list($a, $b), list($c, $d)] = [[1, 2], [3, 4]];
 
// This, however, is allowed:
[[$a, $b], [$c, $d]] = [[1, 2], [3, 4]];

Aside from this restriction, assignment with [] on the left-hand side behaves identically to list() in all respects.

Backward Incompatible Changes

None.

Proposed PHP Version(s)

This is proposed for the next minor or major version of PHP, whichever comes first. At the time of writing, this would be PHP 7.1.

RFC Impact

This RFC has no impact upon OPcache or other extensions dealing with PHP opcodes, because the compiled result is identical to the list() syntax.

This RFC would, however, impact upon projects which try to parse PHP syntax or inspect the PHP interpreter's abstract syntax tree.

Open Issues

None.

Unaffected PHP Functionality

This RFC does not remove nor deprecate the existing list() syntax, and it continues to function identically.

Future Scope

We may wish to introduce destructuring assignment syntax for objects in future.

Vote

Because this proposal affects the language syntax (and also therefore the specification), it is a language change and requires at least a 2/3 majority to be accepted when put to a vote.

The vote will be a simple Yes/No vote on whether or not to accept the RFC for PHP 7.1 and merge the patch into master.

Voting started on 2016-04-27 and ended on 2016-05-08.

Accept the RFC Square bracket syntax for array destructuring assignment for PHP 7.1?
Real name Yes No
ajf (ajf)  
beberlei (beberlei)  
bishop (bishop)  
bwoebi (bwoebi)  
cmb (cmb)  
colinodell (colinodell)  
danack (danack)  
daverandom (daverandom)  
davey (davey)  
dragoonis (dragoonis)  
francois (francois)  
galvao (galvao)  
jhdxr (jhdxr)  
jwage (jwage)  
klaussilveira (klaussilveira)  
krakjoe (krakjoe)  
lbarnaud (lbarnaud)  
leigh (leigh)  
levim (levim)  
lstrojny (lstrojny)  
marcio (marcio)  
mariano (mariano)  
mattwil (mattwil)  
mcmic (mcmic)  
nikic (nikic)  
ocramius (ocramius)  
pauloelr (pauloelr)  
pierrick (pierrick)  
pollita (pollita)  
ralphschindler (ralphschindler)  
rasmus (rasmus)  
rmf (rmf)  
sammyk (sammyk)  
santiagolizardo (santiagolizardo)  
svpernova09 (svpernova09)  
thorstenr (thorstenr)  
tpunt (tpunt)  
treffynnon (treffynnon)  
trowski (trowski)  
weierophinney (weierophinney)  
yohgaki (yohgaki)  
Final result: 41 0
This poll has been closed.

Patches and Tests

There is a pull request, with tests, for the PHP interpreter (php-src) here: https://github.com/php/php-src/pull/1849

There is not yet a patch or pull request for the language specification (php-langspec).

Implementation

Merged into master for PHP 7.1: http://git.php.net/?p=php-src.git;a=commitdiff;h=4f077aee836ad7d8335cf62629a8364bdf939db9

Not yet in the language specification.

After the project is implemented, this section should contain

  1. a link to the PHP manual entry for the feature

References

Rejected Features

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