If I iterate through an array twice, once by reference and then by value, PHP will overwrite the last value in the array if I use the same variable name for each loop. This is best illustrated through an example:
$array = range(1,5);
foreach($array as &$element)
{
$element *= 2;
}
print_r($array);
foreach($array as $element) { }
print_r($array);
Output:
Array ( [0] => 2 [1] => 4 [2] => 6 [3] => 8 [4] => 10 )
Array ( [0] => 2 [1] => 4 [2] => 6 [3] => 8 [4] => 8 )
Note that I am 开发者_JAVA百科not looking for a fix, I am looking to understand why this is happening. Also note that it does not happen if the variable names in each loop are not each called $element
, so I'm guessing it has to do with $element
still being in scope and a reference after the end of the first loop.
After the first loop $element is still a reference to the last element/value of $array.
You can see that when you use var_dump() instead of print_r()
array(5) {
[0]=>
int(2)
...
[4]=>
&int(2)
}
Note that & in &int(2)
.
With the second loop you assign values to $element. And since it's still a reference the value in the array is changed, too. Try it with
foreach($array as $element)
{
var_dump($array);
}
as the second loop and you'll see.
So it's more or less the same as
$array = range(1,5);
$element = &$array[4];
$element = $array[3];
// and $element = $array[4];
echo $array[4];
(only with loops and multiplication ...hey, I said "more or less" ;-))
Here's an explanation from the man himself:
$y = "some test"; foreach ($myarray as $y) { print "$y\n"; }
Here
$y
is a symbol table entry referencing a string containing "some test". On the first iteration you essentially do:$y = $myarray[0]; // Not necessarily 0, just the 1st element
So now the storage associated with
$y
is overwritten by the value from$myarray
. If$y
is associated with some other storage through a reference, that storage will be changed.Now let's say you do this:
$myarray = array("Test"); $a = "A string"; $y = &$a; foreach ($myarray as $y) { print "$y\n"; }
Here
$y
is associated with the same storage as$a
through a reference so when the first iteration does:$y = $myarray[0];
The only place that "Test" string can go is into the storage associated with
$y
.
This is how you would fix this problem:
foreach($array as &$element)
{
$element *= 2;
}
unset($element); #gets rid of the reference and cleans the var for re-use.
foreach($array as $element) { }
精彩评论