PHP foreach 循环在没有任何赋值的情况下修改数组


PHP foreach loop modifies array without any assignment

从两天开始,我真的对这个感到疯狂。如果有人能给我一个提示,我将不胜感激。我绝对不明白为什么这个PHP代码:

$arr [] = [ "name" => "Chapter 1" ];
$arr [] = [ "name" => "Chapter 2" ];
foreach ( $arr as &$item )
    echo $item['name']."<br>";
echo "============<br>";
foreach ( $arr as $item )
    echo $item['name']."<br>";

给出以下输出:

Chapter 1
Chapter 2
============
Chapter 1
Chapter 1      (I would expect 'Chapter 2' here)

看起来第一个循环修改了数组,即使循环中没有赋值。奇怪的是,当我删除与号时,一切都按预期工作。

我不明白的是,为什么数组会被修改,即使我没有对引用变量"&$item"变量做任何事情(除了回显它)。

我还尝试了循环之间的 reset()。但它并没有改变任何东西,根据手册,在这种情况下(至少根据我的理解),无论如何都没有必要,因为循环彼此开始并且不以某种方式嵌套。

多谢!

伯恩德

任何循环完成后,其中使用的变量仍然存在。例如:

for( $i=0; $i<10; $i++) {
    // do something
}
echo $i; // 10

这同样适用于引用。循环完成后,$item仍然是对数组中最后一项的引用。因此,当您第二次写入foreach($arr as $item)时,您现在使用该引用到最后一个元素并重复重新分配它,这会导致数组的最后一个元素被分配(通过引用)与倒数第二个项目相同的东西。

要解决此问题,请务必清理:

unset($item); // delete the reference

从理论上讲,您应该在任何循环后进行清理,但在几乎所有其他情况下,这都无关紧要。只是在这种情况下,它确实如此!

你可以在这里阅读更多 http://pl.php.net/manual/en/control-structures.foreach.php

"为了能够直接修改循环中的数组元素,前面$value &.在这种情况下,该值将通过引用分配。

例:

$arr = array(1, 2, 3, 4);
foreach ($arr as &$value) {
    $value = $value * 2;
}
// $arr is now array(2, 4, 6, 8)
unset($value); // break the reference with the last element

从技术上讲,数组不会在代码示例中进行修改,但引用点附加到其中一个数组值。 如果将示例修改为:

$arr [] = [ "name" => "Chapter 1" ];
$arr [] = [ "name" => "Chapter 2" ];
echo '<pre>';
var_dump($arr);
foreach ( $arr as &$item )
    echo $item['name']."<br>";
echo "============<br>";
var_dump($arr);
foreach ( $arr as $item )
    echo $item['name']."<br>";
echo $item['name'];
您可以检查 var 转储

输出,并在第二个 var 转储中查看引用指针:

array(2) {
    [0]=>
    array(1) {
        ["name"]=>
        string(9) "Chapter 1"
    }
    [1]=>
    array(1) {
        ["name"]=>
        string(9) "Chapter 2"
    }
}
Chapter 1
Chapter 2
============
array(2) {
    [0]=>
    array(1) {
        ["name"]=>
        string(9) "Chapter 1"
    }
    [1]=>
    &array(1) {
        ["name"]=>
        string(9) "Chapter 2"
    }
}
Chapter 1
Chapter 1

我的理论是,这与PHP内部如何处理引用指针有关。 正如其他人所建议的那样,只需在循环之间运行unset($item),您就可以缓解问题。

相关文章: