简体   繁体   English

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

[英]php issue with looping over an array twice using foreach and passing value by reference

I need to loop through an array twice - once to modify its values, and once to display its content in html. 我需要遍历一个数组两次 - 一次修改它的值,一次在html中显示它的内容。 Unfortunately, I am running into trouble. 不幸的是,我遇到了麻烦。 I have created a test scenario to illustrate the issue. 我已经创建了一个测试场景来说明问题。

$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/>';
}

This outputs: 这输出:

Case01 - case style 1
Case02 - case style 2
Case03 - case style 3
Case04 - case style 4
Case05 - case style 5
Case05 - case style 5

Note the values for the last item are wrong. 请注意,最后一项的值是错误的。

If during the second iteration I use foreach($cases as $k => $d) instead of foreach($cases as $k => $v) or if I unset $v before the second iteration (unset($v)) everything goes fine. 如果在第二次迭代期间我使用foreach($cases as $k => $d)而不是foreach($cases as $k => $v)或者如果我在第二次迭代之前取消设置$v (unset($v))一切顺利。 This is intriguing. 这很有趣。 What am I missing? 我错过了什么?

When you execute a foreach loop, the variables in the () persist after the loop is done. 执行foreach循环时, ()的变量在循环完成后仍然存在。 That means that after the first loop finishes, you can var_dump($v) and get the values that were contained in it after the last iteration through the first loop. 这意味着在第一个循环完成后,您可以使用var_dump($v)并获取在第一个循环的最后一次迭代之后包含在其中的值。 This is the case whether it's a reference ( &$v ) or a normal variable ( $v ). 无论是引用( &$v )还是普通变量( $v )都是如此。

However, if it's a reference in the first loop, it remains a reference unless it's unset. 但是,如果它是第一个循环中的引用,它仍然是引用,除非它未设置。 That means when you enter the second loop, you're overwriting the reference with the value of the array element you're currently looking at. 这意味着当您进入第二个循环时,您将使用您当前正在查看的数组元素的值覆盖该引用

Remember, what foreach($cases as $k => $v) really means is "take the key for this element in $cases and assign that to $k, and take the value for this element and assign it to $v)". 请记住, foreach($cases as $k => $v)真正含义是“在$ cases中获取此元素的密钥并将其分配给$ k,并获取此元素的值并将其分配给$ v” 。 Since $v is still a reference to the last element in the array, rather than setting the value of a new variable $v, you're actually updating the value of where $v already points to. 由于$ v仍然是对数组中最后一个元素的引用,而不是设置新变量$ v的值,实际上你正在更新$ v已经指向的值。

What that means is, if we simplify $cases to be simply ['a', 'b', 'c', 'd'] , after the first time through the second foreach, $cases is now ['a', 'b', 'c', 'a'] because you've reassigned the element in $cases that $v points to - the last one - to have the same value as the first one. 这意味着,如果我们简单地将$ case简化为['a', 'b', 'c', 'd'] ,在第一次通过第二次foreach后,$ case现在是['a', 'b', 'c', 'a']因为你已经在$ case中重新分配$ v指向的元素 - 最后一个 - 与第一个具有相同的值。 The second time through, it's ['a', 'b', 'c', 'b'] . 第二次,它是['a', 'b', 'c', 'b'] The third time through it's ['a', 'b', 'c', 'c'] . 第三次通过它['a', 'b', 'c', 'c'] Then, the last time through, you're assigning it to itself, and at that time it holds the value 'c' . 然后,最后一次,你将它分配给自己,并在那时它保持值'c'

This is really just a case of php working as expected. 这实际上只是php按预期工作的情况。 The solution is to unset($v) as soon as the first loop finishes, to make sure that the next time you use $v you're using a new variable, rather than an existing reference. 解决方案是在第一个循环结束后立即unset($v) ,以确保下次使用$ v时您使用的是新变量,而不是现有的引用。

To see this in action: 要看到这个:

Head on over to http://phpfiddle.org/ and paste the following code, and run it; 转到http://phpfiddle.org/并粘贴以下代码,然后运行它; you'll see in the output that $v is maintained after the first loop completes, and that the value of $cases[5] changes each time through the second loop. 你会在输出中看到$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/>';
}

Try this: 试试这个:

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

Let me know is this your solution: 让我知道这是你的解决方案:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM