Как считывается массив в цикле foreach PHP?

Мы все слышали о том, как в цикле for мы должны это сделать:

 for ($i = 0, $count = count($array); $i < $c; ++$i) { // Do stuff while traversing array } 

вместо этого:

 for ($i = 0; $i < count($array); ++$i) { // Do stuff while traversing array } 

по соображениям производительности (т.е. инициализация $count бы count() только один раз, вместо вызова count() с каждой условной проверкой).

Это также имеет значение, если в цикле foreach я делаю это:

 $array = do_something_that_returns_an_array(); foreach ($array as $key => $val) { // Do stuff while traversing array } 

вместо этого:

 foreach (do_something_that_returns_an_array() as $key => $val) { // Do stuff while traversing array } 

при условии, что обстоятельства позволяют мне использовать либо? То есть, PHP вызывает функцию только один раз в обоих случаях, или это похоже for где второй случай будет вызывать функцию снова и снова?

Related of "Как считывается массив в цикле foreach PHP?"

foreach() реализуется с использованием итераторов – поэтому он вызывает только функцию, которая возвращает массив один раз, а затем использует итератор, который указывает на существующий набор результатов для продолжения с каждым элементом.

Я думаю, что тестирование на это обязательно ответит.

Вот мой код:

 function GetArray() { echo "I am called.\n"; return array("One"=>1, "Two"=>2, "Three"=>3, "Four"=>4, "Five"=>5); } echo "Case #1\n"; $array = GetArray(); foreach ($array as $key => $val){ // Do stuff while traversing array echo " Inside the loop: $key => $val\n"; } echo "\n"; echo "Case #2\n"; foreach (GetArray() as $key => $val) { // Do stuff while traversing array echo " Inside the loop: $key => $val\n"; } echo "\n"; 

и вот результат:

 Дело 1
 Меня позвали.
     Внутри цикла: One => 1
     Внутри цикла: Two => 2
     Внутри цикла: Три => 3
     Внутри цикла: Four => 4
     Внутри цикла: Five => 5

 Случай №2
 Меня позвали.
     Внутри цикла: One => 1
     Внутри цикла: Two => 2
     Внутри цикла: Три => 3
     Внутри цикла: Four => 4
     Внутри цикла: Five => 5

Оба они одновременно считывают функцию вызова. Так что ничего другого.

foreach делает копию входного массива и работает на нем на каждой итерации. Поэтому вы можете использовать foreach (do_something_that_returns_an_array() as $key => $val) и он будет вызывать do_something_that_returns_an_array() только один раз.

Я бы привел пример, чтобы узнать, что произойдет. Что-то вроде…

 function do_something_that_returns_an_array() { echo 'I have been called!'; return array('i am an', 'array'); } 

Как вы можете видеть на CodePad, он вызывается только один раз .

Я всегда предполагал, что do_something_that_returns_an_array() работает только один раз, потому что, в отличие от цикла for, нет причин для его запуска несколько раз. Причина, по которой средство проверки правильности цикла работает в конце каждой итерации, заключается в том, чтобы допускать очень сложные проверки.

В качестве теста я сделал следующее:

 function get_array() {echo 5; return array(1,2,3,4,5);} foreach(get_array() as $key => $value) {} 

Сценарий напечатал 5 раз. Поэтому функция get_array() оценивает только один раз.

foreach () работает с объектами Iterator или IteratorAggregate (например, массивы и объекты, реализующие интерфейс). Он не может работать с неизменяемыми объектами. Функции возвращают неизменяемые объекты, поэтому возвращаемый массив должен быть скопирован в объект Iterator перед тем, как он будет выполняться (это делается самим php)