English 中文(简体)
Why does PHP overwrite values when I iterate through this array twice (by reference, by value)
原标题:
  • 时间:2010-04-15 13:10:53
  •  标签:
  • php
  • php-5.3

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 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
";
}

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
";
}

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) { }




相关问题
Brute-force/DoS prevention in PHP [closed]

I am trying to write a script to prevent brute-force login attempts in a website I m building. The logic goes something like this: User sends login information. Check if username and password is ...

please can anyone check this while loop and if condition

<?php $con=mysql_connect("localhost","mts","mts"); if(!con) { die( unable to connect . mysql_error()); } mysql_select_db("mts",$con); /* date_default_timezone_set ("Asia/Calcutta"); $date = ...

定值美元

如何确认来自正确来源的数字。

Generating a drop down list of timezones with PHP

Most sites need some way to show the dates on the site in the users preferred timezone. Below are two lists that I found and then one method using the built in PHP DateTime class in PHP 5. I need ...

Text as watermarking in PHP

I want to create text as a watermark for an image. the water mark should have the following properties front: Impact color: white opacity: 31% Font style: regular, bold Bevel and Emboss size: 30 ...

How does php cast boolean variables?

How does php cast boolean variables? I was trying to save a boolean value to an array: $result["Users"]["is_login"] = true; but when I use debug the is_login value is blank. and when I do ...

热门标签