7

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!

2 Answers 2

4

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) } }
Sign up to request clarification or add additional context in comments.

3 Comments

Just want to say that if anyone wants confirmation: codepad.viper-7.com/hcpoWB Only thing I added was the line with br tag.
"If you don't do this, you will get unpredictable results" --- what tells us the results must be unpredictable? The warning you quoted does not explain the behaviour.
I agree, the results would be very predictable according to the Warning, but this is still a useful answer besides that.
0

If you rewrite following code:

foreach ($array as &$numbers) {
    $numbers = [4, 5, 6];
}

To smth like this:

  $array['numbers'] = &$array['numbers'];
  $array['numbers'] = [4,5,6]; 

It'll be easier to understand such a behavior, and this seems to be a known issue. (See: http://php.net/manual/en/language.references.php#87532)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.