11

我需要遍历一个数组两次——一次是修改它的值,一次是在 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

3 回答 3

20

当您执行一个foreach循环时,()循环完成后变量中的变量仍然存在。这意味着在第一个循环完成后,您可以var_dump($v)通过第一个循环获得最后一次迭代后包含在其中的值。无论是引用 ( &$v) 还是普通变量 ( $v),情况都是如此。

但是,如果它是第一个循环中的引用,则除非未设置,否则它仍然是引用。这意味着当您进入第二个循环时,您将使用当前正在查看的数组元素的值覆盖引用。

请记住,foreach($cases as $k => $v)真正的意思是“在 $cases 中获取此元素的键并将其分配给 $k,并获取此元素的值并将其分配给 $v)”。由于 $v 仍然是对数组中最后一个元素的引用,而不是设置新变量 $v 的值,您实际上是在更新 $v 已经指向的位置的值。

这意味着,如果我们将 $cases 简化为 simple ['a', 'b', 'c', 'd'],在第一次通过第二次 foreach 之后, $cases 现在是['a', 'b', 'c', 'a']因为您已经重新分配了 $cases 中 $v 指向的元素 - 最后一个 - 具有与第一个相同的值。第二次通过,是['a', 'b', 'c', 'b']。第三次通过它['a', 'b', 'c', 'c']。然后,最后一次,你将它分配给它自己,那时它持有 value '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/>';
}
于 2013-09-07T04:34:30.613 回答
2

尝试这个:

foreach ($cases as $k => &$v) {
    $cases[$k]['caseNum'] = ucwords($v['caseNum']);
    echo $cases[$k]['caseNum'] . ' - ' . $cases[$k]['caseStyle'] . '<br/>';
}
于 2013-09-07T04:06:37.143 回答
0

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

foreach ($cases as $k => &$v){
    foreach($v as &$value){ $value = ucwords($value); }
echo $v['caseNum'] . ' - ' . $v['caseStyle'] . '<br/>';
}
于 2013-09-07T04:15:32.830 回答