9

this code produce an unexpected output:

$array=str_split("abcde");
foreach($array as &$item)
    echo $item;

echo "\n";
foreach($array as $item)
    echo $item;

output:

abcde
abcdd

if use &$item for second loop everything works fine.

I don't understand how this code would affect the content of $array. I could consider that an implicit unset($header) would delete the last row but where does the double dd comes from ?

Gabriele Petrioli
  • 191,379
  • 34
  • 261
  • 317
Frederic Bazin
  • 1,530
  • 12
  • 27

1 Answers1

12

This could help:

$array=str_split("abcde");
foreach($array as &$item)
    echo $item;

var_dump($array);

echo "\n";
foreach($array as $item) {
    var_dump($array);
    echo $item;
}

As you can see after the last iteration $item refers to 4th element of $array (e).

After that you iterate over the array and change the 4th element to the current one. So after first iteration of the second loop it will be abcda, etc to abcdd. And in the last iteration you change 4th element to 4th, as d to d

alex
  • 479,566
  • 201
  • 878
  • 984
zerkms
  • 249,484
  • 69
  • 436
  • 539
  • thanks. Is there anyway to "detach" $item from 4th element after the first loop ? – Frederic Bazin Jun 09 '11 at 04:13
  • 3
    @lenzai: `unset($item);` --- it is a common practice to unset reference variable as long as you don't need it anymore to prevent such confusions. – zerkms Jun 09 '11 at 04:16
  • my mistake, i thought unsset($item would delete $array[4]. I guess I was wrong. – Frederic Bazin Jun 09 '11 at 04:20
  • 3
    @lenzai: unset **always** destroys reference. If you have `$a = 1; unset($a);` it destroys the only one reference to `1` placed in memory. As long as there are no any other references - `1` is not accessible anymore with any variable name, so you treat it as "unset". So think of unset as just "some construct that breaks interconnection between variable name and memory, but doesn't modify memory" – zerkms Jun 09 '11 at 04:22
  • 4
    In fact, the documentation of foreach (http://php.net/manual/en/control-structures.foreach.php) specifically talks about this: "Reference of a $value and the last array element remain even after the foreach loop. It is recommended to destroy it by unset(). " – newacct Jan 06 '13 at 22:27