我对引用有一些意想不到的行为:
foreach ($this->data as &$row)
{
$row['h'] = 1;
}
foreach ($this->data as $id => $row)
{
... in some cases $row[$id] = $row;
}
结果是数组的最后一个元素被替换为数组的倒数第二个元素。它由以下代码修复:
foreach ($this->data as $key => $row)
{
$this->data[$key]['h'] = 1;
}
不幸的是,我没有更多时间花在这上面。也许这是PHP的错误(PHP 5.5.9-1ubuntu4)或者我不了解引用的东西?
答案 0 :(得分:1)
有一个完美的逻辑解释,这不是一个错误!
PHP 5引入了直接修改数组内容的可能性,方法是通过引用而不是值将每个元素的值赋值给迭代变量。请考虑此代码,例如:
$a = array (’zero’,’one’,’two’);
foreach ($a as &$v) {
}
foreach ($a as $v) {
}
print_r ($a);
很自然地认为,因为这个小脚本对数组没有任何作用,所以它不会影响它的内容......但事实并非如此!实际上,该脚本提供了以下输出:
Array
(
[0] => zero
[1] => one
[2] => one
)
如您所见,数组已更改,最后一个键现在包含值“one”。怎么可能?正如我们所期望的那样,第一个foreach
循环不会对数组进行任何更改。但是,它确实会为$v
分配对每个$a
元素的引用,因此,当循环结束时,$v
实际上是一个引用到$a[2]
。
第二个循环开始后,$v
现在被赋予每个元素的值。但是,$v
已经是对$a[2]
的引用;因此,分配给它的任何值都将自动复制到数组的最后一个元素中!因此,在第一次迭代期间,$a[2]
将变为零,然后是一个,然后再一次,有效地复制到自身。要解决此问题,您应该始终取消设置在引用foreach
循环中使用的变量 - 或者更好的是,完全避免使用前者。
答案 1 :(得分:0)
通过引用循环遍历数组时,需要在for循环结束时手动释放引用,以避免像这样的奇怪行为。所以你的第一个foreach
应该是:
foreach ($this->data as &$row)
{
.... code ....
}
unset($row);
在这种情况下,unset仅销毁引用,而不是$row
引用的内容。