как на php 'объекту' действительно работает?


foreachforeach

позвольте мне префикс это тем, что я знаю, что это, и как это использовать. этот вопрос касается того, как это работает под капотом, и я не хочу никаких ответов в духе "это как цикл массив ".

foreachcopy

долгое время я предполагал, что работали с самим массивом. потом я нашел много ссылок на то, что он работает с массивом, и с тех пор я предполагал, что это будет конец истории. но недавно я ввязался в дискуссию по этому вопросу, и после недолгих экспериментов обнаружил, что это не было на самом деле 100% правда.

позвольте мне показать, что я имею в виду. для следующих тестов мы будем работать со следующим массивом:

$array = array(1, 2, 3, 4, 5);
test case 1

:

foreach ($array as $item) {  echo "$item\n";  $array[] = $item;}print_r($array);/* output in loop:    1 2 3 4 5   $array after loop: 1 2 3 4 5 1 2 3 4 5 */

это ясно показывает, что мы не работаем напрямую с различными источника - в противном случае цикл будет продолжаться вечно, так как мы постоянно нажимать на элементы массива в цикле. но просто чтобы быть уверенным, это в том случае:

test case 2

:

foreach ($array as $key => $item) {  $array[$key + 1] = $item + 2;  echo "$item\n";}print_r($array);/* output in loop:    1 2 3 4 5   $array after loop: 1 3 4 5 6 7 */
but...

это подтверждает наш первоначальный вывод, мы работаем с копией исходного массива в цикле, в противном случае мы увидим измененные значения в течение цикла.

manual

если мы посмотрим на то , мы находим такое заявление:

when foreach first starts executing, the internal array pointer is automatically reset to the first element of the array.

foreachnot working with the source array

правильно... это, кажется, предполагают, что полагается на указатель массива источник. но мы только что доказали, что мы , верно? ну, не совсем.

test case 3

:

// move the array pointer on one to make sure it doesn't affect the loopvar_dump(each($array));foreach ($array as $item) {  echo "$item\n";}var_dump(each($array));/* output  array(4) {    [1]=>    int(1)    ["value"]=>    int(1)    [0]=>    int(0)    ["key"]=>    int(0)  }  1  2  3  4  5  bool(false)*/
test case 1

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

руководство по php также гласит:

as foreach relies on the internal array pointer changing it within the loop may lead to unexpected behavior.

ну, давайте выясним, что это "неожиданное поведение" (технически, любое поведение является неожиданным, так как я больше не знаю, чего ожидать).

test case 4

:

foreach ($array as $key => $item) {  echo "$item\n";  each($array);}/* output: 1 2 3 4 5 */
test case 5

:

foreach ($array as $key => $item) {  echo "$item\n";  reset($array);}/* output: 1 2 3 4 5 */

...ничего неожиданного нет, на самом деле это, кажется, поддерживает "копировать из источников" теории.

the question

что здесь происходит? мой си-фу-это не достаточно для меня, чтобы смогла извлечь правильные выводы, просто взглянув на исходный код php, я был бы признателен, если кто-то может перевести это на английский для меня.

foreachcopy

мне кажется, что строительство с массива, но устанавливает указатель массива-источника в конец массива после цикла.

  • is this correct and the whole story?
  • if not, what is it really doing?
  • is there any situation where using functions that adjust the array pointer (each(), reset() et al.) during a foreach could affect the outcome of the loop?