【问题标题】:PHP foreach loop modifies array without any assignmentPHP foreach 循环在没有任何赋值的情况下修改数组
【发布时间】:2015-02-24 16:06:50
【问题描述】:

从这两天开始,我真的很疯狂。如果有人能给我一个提示,我将不胜感激。我绝对不明白为什么这个 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()。但它并没有改变任何东西,根据手册,在这种情况下无论如何都不需要(至少根据我的理解),因为循环是一个接一个地开始的,并且不会以某种方式嵌套。

非常感谢!

伯纳德

【问题讨论】:

  • 从第一个 foreach 中的 &$item 中删除 "&" :-)
  • 在第一个循环之后立即添加unset($item)
  • 是的,这将是最简单的方法:-)。但是上面的 sn-p 只是我为了显示基本问题而剥离的一段代码。我无法删除它的原因是,在实际代码中,我确实需要从循环中修改数组。当然,'for' - 循环也可以很好地工作,但我不喜欢仅仅因为我不了解最初的问题而构建变通方法。

标签: php arrays loops foreach reference


【解决方案1】:

从技术上讲,您的代码示例中并未对数组进行修改,但参考点已附加到您的数组值之一。如果您将示例修改为:

$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 dump 中的引用指针:

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) 即可缓解此问题。

【讨论】:

    【解决方案2】:

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

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

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

    要修复,请务必清理:

    unset($item); // delete the reference
    

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

    【讨论】:

    • 是的,行得通。非常感谢您令人信服的快速、良好和详细的解释!简直太棒了!!!
    【解决方案3】:

    您可以在这里阅读更多内容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
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-08-03
      相关资源
      最近更新 更多