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

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


When you execute a foreach loop, the variables in the () persist after the loop is done. 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. This is the case whether it's a reference (&$v) or a normal variable ($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)". 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.

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. The second time through, it's ['a', 'b', 'c', 'b']. The third time through it's ['a', 'b', 'c', 'c']. Then, the last time through, you're assigning it to itself, and at that time it holds the value 'c'.

This is really just a case of php working as expected. 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.

To see this in action:

Head on over to http://phpfiddle.org/ and paste the following code, and run it; 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.

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