[英]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.