foreach makes a copy of the input array and works on that in each iteration. So you can use foreach (do_something_that_returns_an_array() as $key => $val) and it'll call do_something_that_returns_an_array() only once.

That wording is not quite correct. Technically PHP arrays are copy-on-write so when you say the array is copied, the wording is at best ambiguous and at worst misleading. The return value is simply used "as is".
–
cletusJul 25 '10 at 13:32

I've always assumed that do_something_that_returns_an_array() only runs once because, unlike in the for loop, there's no reason for it to run multiple times. The reason the for loop truth checker runs at the end of every iteration is to allow for very complicated checkers.

foreach() works with Iterator or IteratorAggregate objects (e.g., arrays and objects implementing the interface). It can't work with immutable objects. Functions return immutable objects, so the returning array have to be copied into Iterator object before foreaching (it's made by php itself)

immutable == very constant :) you cant change the object which is returned by function in php, it can't be used by L-Value (f() = 1 fails, either, i think, will array_push(f(), 123) )
–
Valentin GolevNov 6 '09 at 6:10

Functions don't return immutable objects. Due to the particularities of object references, you can dereference the object and do getObject()->foo = 'bar' quite fine (and if there's a reference to the object, it gets updated)... You can't dereference arrays (getArray()['foo'] doesn't work). But there is no such thing as an immutable object in PHP. You can always dereference or modify an object (access restrictions not withstanding).
–
ircmaxellOct 11 '10 at 17:34