I want to pass a two-dimensional array by reference with foreach

Aug 25, 2020 PHP

Thing you want to do

I want to update a part of the following two-dimensional array.

$tests = [['values'=>[1,2]],['values'=>[3,4]]];

#Environment (including items not related to this work)

Implementation

First, basic pass by reference

Add & to the variable used in foreach.

$tests = [1,2,3,4];
foreach ($tests as &$test) {
    if($test === 3) {
        $test = 5;
    }
}
$test = 6;
var_dump($tests);

/*
array (size=4)
  0 => int 1
  1 => int 2
  2 => int 5
  3 => int 6 ← funny
*/

In the above case, the pointer to $test remains, so if you use the same variable name after issuing foreach, the array data will be updated. Note that you need to unset it like this:

$tests = [1,2,3,4];
foreach ($tests as &$test) {
    if($test === 3) {
        $test = 5;
    }
}
unset($test);
$test = 6;
var_dump($tests);

/*
array (size=4)
  0 => int 1
  1 => int 2
  2 => int 5
  3 => int 4 ← correct
*/

There is no wondering what the specifications are.

Two-dimensional array passing by reference

Turn foreach in double. Adding & only to the second foreach does not work.

$tests = [['values'=>[1,2]],['values'=>[3,4]]];
foreach ($tests as $test) {
    foreach ($test['values'] as &$value) {
        if($value === 2){
            $value = 5;
        }
    }
    unset($value);
}
var_dump($tests);

/*
array (size=2)
  0 =>
    array (size=1)
      'values' =>
        array (size=2)
          0 => int 1
          1 => int 2 ← funny
  1 =>
    array (size=1)
      'values' =>
        array (size=2)
          0 => int 3
          1 => int 4
*/

Adding & to both will work.

$tests = [['values'=>[1,2]],['values'=>[3,4]]];
foreach ($tests as &$test) {
    foreach ($test['values'] as &$value) {
        if($value === 2){
            $value = 5;
        }
    }
    unset($value);
}
unset($test);

/*
array (size=2)
  0 =>
    array (size=1)
      'values' =>
        array (size=2)
          0 => int 1
          1 => int 5 ← correct
  1 =>
    array (size=1)
      'values' =>
        array (size=2)
          0 => int 3
          1 => int 4
*/