Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Adding references in PHP to an array creates an array of references

Not sure if this is considered a bug

$array = ['numbers' => [1, 2, 3]];
foreach ($array as &$numbers) {
    $numbers = [4, 5, 6];
}
var_dump($array);
modify_array($array);
var_dump($array);

function modify_array($array_arg)
{
    $array_arg['numbers'] = [1, 2, 3];
}

Prints

array(1) {
  ["numbers"]=>
  &array(3) {
    [0]=>
    int(4)
    [1]=>
    int(5)
    [2]=>
    int(6)
  }
}
array(1) {
  ["numbers"]=>
  &array(3) {
    [0]=>
    int(1)
    [1]=>
    int(2)
    [2]=>
    int(3)
  }
}

Notice that $array was not passed by reference to modify_array() however the nested array was modified. It sounds logical but not sure if this is documented!

like image 850
Gadelkareem Avatar asked Sep 17 '14 23:09

Gadelkareem


1 Answers

If you are using foreah with reference you prevent PHP to make a copy of array, so you are working on original array. When you finish foreach loop you should unset() variable used in loop, because it still remains in memory. If you don't do this, you will get unpredictable results like this one presented in your question. Even in documentation you have a warning:

Warning Reference of a $value and the last array element remain even after the foreach loop. It is recommended to destroy it by unset().

Here you can find really good examples of foreach loops without unsetting.

So if you add unset(), everything looks as it should

$array = ['numbers' => [1, 2, 3]];
foreach ($array as &$numbers) {
    $numbers = [4, 5, 6];
}
unset($numbers);
var_dump($array);
modify_array($array);
var_dump($array);

function modify_array($array_arg) {
    $array_arg['numbers'] = [1, 2, 3];
}

Result:

array(1) { ["numbers"]=> array(3) { [0]=> int(4) [1]=> int(5) [2]=> int(6) } } 
array(1) { ["numbers"]=> array(3) { [0]=> int(4) [1]=> int(5) [2]=> int(6) } }
like image 184
marian0 Avatar answered Sep 29 '22 13:09

marian0