4

I found a snippet of code in php documentation that I don't understand. I really don't understand if it is a php failure or a shortcoming of mine.

Here the code:

$arr = array('a'=>'first', 'b'=>'second', 'c'=>'third');
foreach ($arr as &$a); // do nothing. maybe?
foreach ($arr as $a);  // do nothing. maybe?
print_r($arr);
?>

Output:

Array
(
    [a] => first
    [b] => second
    [c] => second
)

Add 'unset($a)' between the foreachs to obtain the 'correct' output:

Array
(
    [a] => first
    [b] => second
    [c] => third
)

link: http://php.net/manual/en/language.references.php

Why this behavior? Thanks in advance

vitosdc
  • 43
  • 3
  • possible duplicate of [PHP Foreach Pass by Reference: Last Element Duplicating? (Bug?)](http://stackoverflow.com/questions/8220399/php-foreach-pass-by-reference-last-element-duplicating-bug) – HamZa Jan 14 '15 at 15:02
  • possible duplicate of [PHP Pass by reference in foreach](http://stackoverflow.com/questions/3307409/php-pass-by-reference-in-foreach) – HamZa Jan 14 '15 at 15:04
  • [I've had this problem](http://blog.jondh.me.uk/2011/05/seriously-fiendish-php-gotcha/), it can be very awkward to debug. Avoid `foreach` loops with the reference operator if you can. – halfer Jan 14 '15 at 15:07

1 Answers1

8
foreach ($arr as &$a); // do nothing. maybe?
                 ^---

Once you create a variable as a reference, it STAYS a reference. So in your next foreach, $a will be pointing at the last element of $arr, as it was when the first foreach finished.

Doing unset() in between removes the reference.

Marc B
  • 356,200
  • 43
  • 426
  • 500
  • In other words, it's to do with the lack of block-level scoping. It's like writing `for($i=0; $i<10; $i++) {} echo $i;` and being surprised that you get 10. – Niet the Dark Absol Jan 14 '15 at 14:59
  • For reference, [from the docs](http://php.net/manual/en/control-structures.foreach.php): "**Warning**: Reference of a `$value` and the last array element remain even after the foreach loop. It is recommended to destroy it by `unset()`." – sjagr Jan 14 '15 at 14:59