我需要遍历一个数组两次 - 一次修改它的值,一次在html中显示它的内容。不幸的是,我遇到了麻烦。我已经创建了一个测试场景来说明问题。
$cases = array(
array('caseStyle' => 'case style 1', 'caseNum' => 'case01'),
array('caseStyle' => 'case style 2', 'caseNum' => 'case02'),
array('caseStyle' => 'case style 3', 'caseNum' => 'case03'),
array('caseStyle' => 'case style 4', 'caseNum' => 'case04'),
array('caseStyle' => 'case style 5', 'caseNum' => 'case05'),
array('caseStyle' => 'case style 6', 'caseNum' => 'case06')
);
foreach ($cases as $k => &$v) {
$v['caseNum'] = ucwords($v['caseNum']);
}
foreach ($cases as $k => $v) {
echo $v['caseNum'] . ' - ' . $v['caseStyle'] . '<br/>';
}
输出:
Case01 - case style 1
Case02 - case style 2
Case03 - case style 3
Case04 - case style 4
Case05 - case style 5
Case05 - case style 5
请注意最后一项的值是错误的。
如果在第二次迭代中我使用
foreach($cases as $k => $d)
代替foreach($cases as $k => $v)
或者如果我在第二次迭代$v
之前取消设置(unset($v))
,一切都会好起来的。这很有趣。我错过了什么?
答案 0 :(得分:17)
执行foreach
循环时,()
中的变量在循环完成后仍然存在。这意味着在第一个循环结束后,您可以var_dump($v)
并获取在第一个循环的最后一次迭代之后包含在其中的值。无论是引用(&$v
)还是普通变量($v
)都是如此。
但是,如果它是第一个循环中的引用,它仍然是引用,除非它未设置。这意味着当您进入第二个循环时,您将使用当前正在查看的数组元素的值覆盖引用。
请记住,foreach($cases as $k => $v)
的真正含义是“在$ cases中获取此元素的键并将其分配给$ k,并获取此元素的值并将其分配给$ v)”。由于$ v仍然是对数组中最后一个元素的引用,而不是设置新变量$ v的值,实际上你正在更新$ v已经指向的值。
这意味着,如果我们将$ case简化为['a', 'b', 'c', 'd']
,那么在第一次通过第二次foreach之后,$ cases现在是['a', 'b', 'c', 'a']
,因为你已经在$ case中重新分配了元素$ v指向 - 最后一个 - 与第一个具有相同的值。第二次,它是['a', 'b', 'c', 'b']
。第三次通过['a', 'b', 'c', 'c']
。然后,在最后一次,您将其分配给自己,并且在那时它保留值'c'
。
这实际上只是php按预期工作的情况。一旦第一个循环结束,解决方案就是unset($v)
,以确保下次使用$ v时您使用的是新变量,而不是现有的参考。
要查看此操作:
转到http://phpfiddle.org/并粘贴以下代码,然后运行它;您将在输出中看到在第一个循环完成后保留$v
,并且$cases[5]
的值每次都会在第二个循环中更改。
$cases = array(
array('caseStyle' => 'case style 1', 'caseNum' => 'case01'),
array('caseStyle' => 'case style 2', 'caseNum' => 'case02'),
array('caseStyle' => 'case style 3', 'caseNum' => 'case03'),
array('caseStyle' => 'case style 4', 'caseNum' => 'case04'),
array('caseStyle' => 'case style 5', 'caseNum' => 'case05'),
array('caseStyle' => 'case style 6', 'caseNum' => 'case06')
);
foreach ($cases as $k => &$v) {
$v['caseNum'] = ucwords($v['caseNum']);
}
var_dump($v);
echo "<br />";
foreach ($cases as $k => $v) {
print_r($cases);
echo "<br />";
echo $k . ': ' . $v['caseNum'] . ' - ' . $v['caseStyle'] . '<br/>';
}
答案 1 :(得分:2)
试试这个:
foreach ($cases as $k => &$v) {
$cases[$k]['caseNum'] = ucwords($v['caseNum']);
echo $cases[$k]['caseNum'] . ' - ' . $cases[$k]['caseStyle'] . '<br/>';
}
答案 2 :(得分:2)
这是一个类似的问题,对于为什么会出现这个问题有一些很好的解释。
答案 3 :(得分:0)
让我知道这是你的解决方案:
foreach ($cases as $k => &$v){
foreach($v as &$value){ $value = ucwords($value); }
echo $v['caseNum'] . ' - ' . $v['caseStyle'] . '<br/>';
}