Wednesday, December 16, 2009

Foreach His Own

I quite often use the foreach() loop in PHP to easily modify an array by passing the array elements by reference, like so:
$testArray = array('one','two','three');

foreach($testArray as &$v) {
// whatever
}


But today this got me into a little trouble. The variables created by the foreach() loop, whether passed by reference or not, continue to exist after the loop has been closed. Thus in the previous example, after the loop is finished $v will continue to point to the last element of $testArray, by reference. Using another foreach() with the variable $v will alter the values in $testArray.
$testArray = array('one','two','three');

foreach($testArray as $k => $v) {
echo "$k: $v<br />";
}

foreach($testArray as &$v) {
// whatever
}

foreach($testArray as $k => $v) {
echo "$k: $v<br />";
}


In this example, the first foreach() echoes the original content of the array. The second foreach() does nothing except pass the array elements by reference. The third foreach() attempts to echo the content of the array but inadvertently alters its last element.

Output:
0: one
1: two
2: three
0: one
1: two
2: two


The first foreach() uses $v to store values and thus leaves it containing the value of the last element of the array. The second foreach() uses $v to hold references and thus leaves it containing a reference to the last element of the array. The third foreach() tries to store values in $v just like the first one did, but this time it contains a reference, so the values are actually stored in the last element of the array, overwriting whatever value was there before.

To make sure this doesn't happen to you like it did to me, simply unset the variables your loops use for references:
foreach($testArray as &$v) {
// whatever
}
unset($v);

Labels: