php问题,使用foreach循环数组两次并通过引用传递值

时间:2013-09-07 03:48:53

标签: php arrays reference foreach iteration

我需要遍历一个数组两次 - 一次修改它的值,一次在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)),一切都会好起来的。这很有趣。我错过了什么?

4 个答案:

答案 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)

这是一个类似的问题,对于为什么会出现这个问题有一些很好的解释。

PHP Pass by reference in foreach

答案 3 :(得分:0)

让我知道这是你的解决方案:

foreach ($cases as $k => &$v){
    foreach($v as &$value){ $value = ucwords($value); }
echo $v['caseNum'] . ' - ' . $v['caseStyle'] . '<br/>';
}