phparraysforeachappenddestructuring

While destructuring array data in the head of a foreach() loop, can new elements be assigned to the original input array?


Since PHP7.1, a foreach() expression can implement array destructuring as a way of unpacking row values and make individualized variable assignments for later use.

When using array destructuring within the head/signature of a foreach() loop, can new elements be declared instead of merely being accessed?

For example:

$array = [
    ['foo' => 'a', 'bar' => 1],
    ['foo' => 'b', 'bar' => 2],
];

Can I append a new element to each row of the original array with the key new?


Solution

  • Yes, data can be appended to the rows of the original input array directly in the head of a foreach().

    A general benefit of using array destructuring is the ability to specifically access/isolate data within a given array without loading unneeded data into a variable.

    Details:

    Code: (Demo)

    $array = [
        ['foo' => 'a', 'bar' => 1],
        ['foo' => 'b', 'bar' => 2],
    ];
    
    foreach ($array as ['new' => &$x, 'bar' => $x]);
    
    var_export($array);
    

    Output:

    array (
      0 => 
      array (
        'foo' => 'a',
        'bar' => 1,
        'new' => 1,
      ),
      1 => 
      array (
        'foo' => 'b',
        'bar' => 2,
        'new' => 2,
      ),
    )
    

    Using the above sample input array, a body-less loop can be used to assign the first level keys as a new column in the array without declaring the full row as a reference. Code: (Demo)

    foreach ($array as $x => ['new' => &$x]);
    

    This approach requires one less globally-scoped variable to be declared versus:

    foreach ($array as $x => &$row) {
        $row['new'] = $x;
    }
    

    and if not modifying by reference, the foreach() signature's required value variable isn't even used.

    foreach ($array as $x => $row) {
        $array[$x]['new'] = $x;
    }
    

    Output (from all):

    array (
      0 => 
      array (
        'foo' => 'a',
        'bar' => 1,
        'new' => 0,
      ),
      1 => 
      array (
        'foo' => 'b',
        'bar' => 2,
        'new' => 1,
      ),
    )
    

    Here is another answer that uses this technique and assigns values to the reference variables via another loop.


    @Dharman mentioned in a PHP internals thread that array destructuring without a foreach() executes the same behavior. Demo

    $arr = [];
    ['foo' => &$v] = $arr;
    $v = 1;
    var_export($arr);
    // output: array('foo' => 1)
    

    Although no longer supported, it was recommended that I clarify that for PHP7.1 through PHP7.2, this technique will cause a fatal error.

    Fatal error: [] and list() assignments cannot be by reference