I'm testing the performances/hitches for References over copies of an array. I have the following code:
function ScoreWords($Value){
$WordList = array(
"Amazing" => 1,
"Value" => 300,
"Elements" => 30,
"Another" => 0
);
if (array_key_exists($Value,$WordList)){
return $WordList[$Value];
}
}
$array = ["Value","Another",1,2,3,4];
echo implode(',', $array), "<br>";
foreach ($array as &$value) {
ScoreWords($value);
}
echo implode(',', $array), "<br>";
foreach ($array as $value) {
ScoreWords($value);
}
echo implode(',', $array), "<br>";
But it seems, the code pasted above works semi-fine. Output is:
Value,Another,1,2,3,4
Value,Another,1,2,3,4
Value,Another,1,2,3,3
I found this by mistake as imploding was not actually necessary, but this sparks the question. Why is there a duplicated value for the final print rather than the correct value of 4
? regardless of what the content of the array is. It seems to duplicate the second from last element as the last element?
What is happening is that after your 1st foreach
, $value
is a reference to the last element in the array. As that loop progressed it was a reference to each element, until finally stopping at the last one.
So, when the 2nd foreach
runs, $value
is still a reference. As that loop runs, it updates $value
, which in turn, updates the last element in the array.
When it gets to the last element, it was set to 3 from the previous loop iteration. So, that's why it's set to 3 at the end.
To fix this, unset($value);
after your first foreach
.
The thing here is that you have to unset
the value when you pass it by reference:
foreach ($array as &$value) {
ScoreWords($value);
}
unset($value); // break the reference with the last element
Warning Reference of a $value and the last array element remain even after the foreach loop. It is recommended to destroy it by unset().