I've come by a case where values in a foreach are passed by reference in order to modify the element, then at a later stage in the code, the same array is looped again to do some calculation but this time the elements are passed by value. The issue is that PHP retains the reference to the last element in the array in the first foreach, then overwrites that element when the next foreach starts if the local variable has the same name.
Example code:
<?php
$a = array("a" => "foo");
$b = array("b" => "bar");
$x = array($a, $b);
foreach ($x as &$y) {}
print_r($x);
foreach ($x as $y) {}
print_r($x);
?>
This will yield
Array
(
[0] => Array
(
[a] => foo
)
[1] => Array
(
[b] => bar
)
)
Array
(
[0] => Array
(
[a] => foo
)
[1] => Array
(
[a] => foo
)
)
This absurdity is stated in the PHP manual
Warning Reference of a $value and the last array element remain even after the foreach loop. It is recommended to destroy it by unset().
And indeed, using unset($y) will resolve the issue. But this is very fragile and you cannot rely on the coder always remembering to unset a variable which scope isn't obvious. So my question is: Are there any good alternatives to foreach-pass-by-reference that eliminates the need to unset the variable afterwards?
You can use array_walk():
array_walk($x, function(&$y) {
/* ... */
});
This makes the reference $y local to the scope of the callback function so that unsetting is handled automatically.
You can use ASSOCIATIVE (indexed) foreach:
foreach ($x as $index=>$y)
{
if ($y=='remove') {unset($x[$index]);}
}
This way you can modify the original array elements easily ...
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With