In a blog post "PHP Internals: When does foreach copy", NikiC stated that in a code like this:
Snippet 1
$array = range(0, 100000);
foreach ($array as $key => $value) {
xdebug_debug_zval('array'); // array is not copied, only refcount is increased
}
foreach
will not copy the array because the only thing that foreach
modifies about $array
is it's internal array pointer.
He also stated that in a code like this:
Snippet 2
$array = range(0, 100000); // line 1
test($array);
function test($array) {
foreach ($array as $key => $value) { // line 4
xdebug_debug_zval('array'); // array is copied, refcount not increased
// ...
}
}
foreach
will copy the array because if it didn't, the $array
variable in line 1 would be changed.
However, the only thing that foreach
modifies about $array
is it's internal array pointer. So why does it matter if the internal array pointer of the $array
variable in line 1 is changed? It didn't matter in snippet 1, why did it matter in snippet 2?
Why does foreach
need to copy the array in snippet 2, even though we did not modify it in the loop?
Summary. To summarize: foreach will copy the array structure if and only if the iterated array is not referenced and has a refcount > 1. foreach will additionally copy the array values if and only if the previous point applies and the iteration is done by reference.
forEach() does not mutate the array on which it is called.
This is an example why pass-by-reference in foreach loops is BAD. This is because when the second loop executes, $entry is still a reference. Thus, with each iteration the original reference is overwritten.
The forEach method is also used to loop through arrays, but it uses a function differently than the classic "for loop". The forEach method passes a callback function for each element of an array together with the following parameters: Current Value (required) - The value of the current array element.
Your question is answered in the article you linked to. It is given in the section
Not referenced, refcount > 1
with the explanation that a copy of the structures is needed because the array pointer moves, and this must not affect the outside array.
That is because in the second case, $array is passed by value to the function test()
. Hence, a copy of the $array was made inside the function, and the foreach()
works on the copy. Things will be different if the $array is passed by reference to the function test()
.
For information on pass by value vs pass by reference, see this question
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