最近在PHP应用中遇到了这个bug。不知道发生了什么。
基本上,当使用两个foreach
(一个带&一个没有)的组合时会出现。
这是一个重现问题的测试代码:
$items = array(
array('id'=>1, 'name'=>'foo', 'value'=>150),
array('id'=>2, 'name'=>'bar', 'value'=>190)
);
foreach($items as &$item)
{
$item['percentage'] = $item['value'] * 0.75;
}
var_dump($items); // All Good
foreach($items as $item)
{
var_dump($item); // Shows 1st item twice
}
第二个foreach
循环按预期运行块两次,但$item
仍然停留在第一个项目上。
我知道在第一个循环中使用引用&
可能会导致 ,但我不明白为什么它应该像这样......
有什么想法吗?那是一个错误吗?
在5.3.8,5.3.10&amp ;;上获得相同的结果5.4
答案 0 :(得分:2)
首先,这不是Rasmus所说的错误。见https://bugs.php.net/bug.php?id=29992
在这个中,正确实现了使用&。
的循环变量修改数组<?php
$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
var_dump($arr); // All Good
foreach($arr as $value) {
var_dump($value); // All good
}
?>
答案 1 :(得分:1)
这是奇怪的PHP行为,它几乎永远存在,当你混合使用变量作为参考而不是像你那样引用时就会发生。
我使用以下命名约定处理它:当我使用foreach
&$item
时,我将其命名为&$refItem
。这使我无法混合类型。
答案 2 :(得分:0)
使用带有引用数组的foreach后,需要取消设置指针。
答案 3 :(得分:0)
这可能是看起来更加了解foreach的问题
$last_value_of_first_foreach = 1;
$item = 2;
$c = 3;
$item = &$last_value_of_first_foreach ; // Think that this statement is first foreach loop
// Here $item is pointer to $last_value_of_first_foreach
// To Better understanding, let change the name ($reference_to_last_value = $item;)
现在,新循环是
$item = $c;
// Here, what it do is update value where the $item pointer refer to
// (mean $last_value_of_first_foreach )
// so, at here $last_value_of_first_foreach has value of $c
现在,回到你的情况,从第一个foreach,$ item引用到数组的最后一个元素。现在,当你在第二个foreach中为$ item分配一些东西时,它会做什么,就会把东西放在那个东西里面。
在第一个循环结束时 $ item是指针到$ items [1] 第二个循环的第一个 它会将第一个元素推送到$ item指向的位置(表示$ items [1],这样为什么$ items [1]被$ items [0]替换。
如果你想阻止这个,只需在下次使用之前取消设置 $ item变量。
答案 4 :(得分:0)
这是正常的,而不是奇怪的行为。请阅读有关参考here的信息。
当你添加&amp;在变量前面,存储对变量的引用。因此,当您重新使用它时,它也会更改引用变量的内容。
foreach($items as &$item) // You have $item here, prefixed with &.
{
$item['percentage'] = $item['value'] * 0.75;
}
var_dump($items);
foreach($items as $item) // And your re-use it here.
{
var_dump($item);
}
要解决此问题,请在第一个循环中添加unset($ item):
foreach($items as &$item)
{
$item['percentage'] = $item['value'] * 0.75;
unset($item); // add this, because you use &$item previously.
}