PHP foreach循环修改数组而不进行任何赋值

时间:2014-12-27 23:38:14

标签: php arrays loops foreach reference

自从两天以来,我真的对此感到疯狂。如果有人能给我一个提示,我会非常感激。我绝对不能理解为什么这个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)

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

我不明白的是,为什么阵列会被修改,即使我没有对参考变量&#39;&amp; $ item&#39;做任何事情。变量(除了回声)。

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

非常感谢!

贝恩德

3 个答案:

答案 0 :(得分:1)

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

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

同样适用于参考文献。循环完成后,$item仍然是对数组中最后一项的引用。因此,当您第二次写foreach($arr as $item)时,您现在正在使用对最后一个元素的引用并重复分配它,这会导致数组的最后一个元素(通过引用)分配相同的元素作为倒数第二项的事情。

要修复,请务必清理:

unset($item); // delete the reference

理论上你应该在任何循环后清理,但在几乎所有其他情况下它都不重要。只是在这种情况下,确实如此!

答案 1 :(得分:0)

您可以在此处阅读更多内容http://pl.php.net/manual/en/control-structures.foreach.php

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

示例:

$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

答案 2 :(得分:0)

在您的代码示例中,数组在技术上没有被修改,但是参考点被附加到您的一个数组值。如果您将示例修改为:

$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 dump输出并查看第二个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)即可解决问题。