Цикл for each от a до z. О тонкостях работы foreach в PHP

(PHP 4, PHP 5, PHP 7)

Конструкция foreach предоставляет простой способ перебора массивов. Foreach работает только с массивами и объектами, и будет генерировать ошибку при попытке использования с переменными других типов или неинициализированными переменными. Существует два вида синтаксиса:

foreach (array_expression as $value) statement foreach (array_expression as $key => $value) statement

Первый цикл перебирает массив, задаваемый с помощью array_expression . На каждой итерации значение текущего элемента присваивается переменной $value и внутренний указатель массива увеличивается на единицу (таким образом, на следующей итерации цикла работа будет происходить со следующим элементом).

Второй цикл будет дополнительно соотносить ключ текущего элемента с переменной $key на каждой итерации.

Замечание :

Когда оператор foreach начинает исполнение, внутренний указатель массива автоматически устанавливается на первый его элемент Это означает, что нет необходимости вызывать функцию reset() перед использованием цикла foreach .

Так как оператор foreach опирается на внутренний указатель массива, его изменение внутри цикла может привести к непредсказуемому поведению.

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

$arr = array(1 , 2 , 3 , 4 );
foreach ($arr as & $value ) {
$value = $value * 2 ;
}
// массив $arr сейчас таков: array(2, 4, 6, 8)
unset($value ); // разорвать ссылку на последний элемент
?>

Указатель на $value возможен, только если на перебираемый массив можно ссылаться (т.е. если он является переменной). Следующий код не будет работать:

foreach (array(1 , 2 , 3 , 4 ) as & $value ) {
$value = $value * 2 ;
}
?>

Внимание

Ссылка $value на последний элемент массива остается даже после того, как оператор foreach завершил работу. Рекомендуется уничтожить ее с помощью функции unset() .

Замечание :

Оператор foreach не поддерживает возможность подавления сообщений об ошибках с помощью префикса "@".

Вы могли заметить, что следующие конструкции функционально идентичны:


reset ($arr );
while (list(, $value ) = each ($arr )) {
echo "Значение: $value
\n" ;
}

foreach ($arr as $value ) {
echo "Значение: $value
\n" ;
}
?>

Следующие конструкции также функционально идентичны:

$arr = array("one" , "two" , "three" );
reset ($arr );
while (list($key , $value ) = each ($arr )) {

\n" ;
}

foreach ($arr as $key => $value ) {
echo "Ключ: $key ; Значение: $value
\n" ;
}
?>

Вот еще несколько примеров, демонстрирующие использование оператора:

/* Пример 1: только значение */

$a = array(1 , 2 , 3 , 17 );

foreach ($a as $v ) {
echo "Текущее значение переменной \$a: $v .\n" ;
}

/* Пример 2: значение (для иллюстрации массив выводится в виде значения с ключом) */

$a = array(1 , 2 , 3 , 17 );

$i = 0 ; /* только для пояснения */

Foreach ($a as $v ) {
echo "\$a[ $i ] => $v .\n" ;
$i ++;
}

/* Пример 3: ключ и значение */

$a = array(
"one" => 1 ,
"two" => 2 ,
"three" => 3 ,
"seventeen" => 17
);

foreach ($a as $k => $v ) {
echo "\$a[ $k ] => $v .\n" ;
}

/* Пример 4: многомерные массивы */
$a = array();
$a [ 0 ][ 0 ] = "a" ;
$a [ 0 ][ 1 ] = "b" ;
$a [ 1 ][ 0 ] = "y" ;
$a [ 1 ][ 1 ] = "z" ;

foreach ($a as $v1 ) {
foreach ($v1 as $v2 ) {
echo " $v2 \n" ;
}
}

/* Пример 5: динамические массивы */

Foreach (array(1 , 2 , 3 , 4 , 5 ) as $v ) {
echo " $v \n" ;
}
?>

Распаковка вложенных массивов с помощью list()

(PHP 5 >= 5.5.0, PHP 7)

В PHP 5.5 была добавлена возможность обхода массива массивов с распаковкой вложенного массива в переменные цикла, передав list() в качестве значения.

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

В данном уроке мы рассмотрим конструкцию foreach при организации цикла по индексированным и ассоциированным массивам.

Цикл по значениям элементов

Самый простой случай использования foreach - это организация цикла по значениям в индексированном массиве. Основной синтаксис:

Foreach ($array as $value) { // Делаем что-нибудь с $value } // Здесь код выполняется после завершения цикла

Например, следующий скрипт проходит по списку режисеров в индексированном массиве и выводит имя каждого:

$directors = array("Alfred Hitchcock", "Stanley Kubrick", "Martin Scorsese", "Fritz Lang"); foreach ($directors as $director) { echo $director . "
"; }

Выше приведенный код выведет:

Alfred Hitchcock Stanley Kubrick Martin Scorsese Fritz Lang

Цикл по ключам и значениям

А что насчет ассоциированных массивов? При использовании такого типа массивов часто нужно иметь доступ к ключу каждого элемента, так же как и к его значению. Конструкция foreach имеет способ решить поставленную задачу:

Foreach ($array as $key => $value) { // Делаем что-нибудь с $key и/или с $value } // Здесь код выполняется после завершения цикла

Пример организации цикла по ассоциированному массиву с информацией о кинофильмах, выводит ключ каждого элемента и его значение в HTML списке определений:

$movie = array("title" => "Rear Window", "director" => "Alfred Hitchcock", "year" => 1954, "minutes" => 112); echo "

"; foreach ($movie as $key => $value) { echo "
$key:
"; echo "
$value
"; } echo "
";

Данный скрипт при выполнении выведет:

Title: Rear Window director: Alfred Hitchcock year: 1954 minutes: 112

Изменение значения элемента

А как обстоит дело с изменением значения элемента при проходе цикла? Вы можете попробовать такой код:

Foreach ($myArray as $value) { $value = 123; }

Однако, если запустить его на выполнение, то вы обнаружите, что значения в массиве не изменяются . Причина заключается в том, что foreach работает с копией значений массива, а не с оригиналом. Таким образом оригинальный массив остается нетронутым.

Для изменения значений массива вам нужна ссылка на значение. Для этого нужно поставить знак & перед переменной значения в конструкции foreach:

Foreach ($myArray as &$value) { $value = 123; }

Например, следующий скрипт проходит циклом каждый элемент (имя режиссера) в массиве $directors , и использует функцию PHP explode() и конструкцию list для перемены мест имени и фамилии:

$directors = array("Alfred Hitchcock", "Stanley Kubrick", "Martin Scorsese", "Fritz Lang"); // Изменяем формат имени для каждого элемента foreach ($directors as &$director) { list($firstName, $lastName) = explode(" ", $director); $director = "$lastName, $firstName"; } unset($director); // Выводим конечный результат foreach ($directors as $director) { echo $director . "
"; }

Скрипт выведет:

Hitchcock, Alfred Kubrick, Stanley Scorsese, Martin Lang, Fritz

Отметим, что скрипт вызывает функцию unset() для удаления переменной $director после завершения первого цикла. Это хорошая практика, если вы планируете использовать переменную позже в скрипте в другом контексте.

Если не удалять ссылку, то есть риск при дальнейшем выполнении кода случайной ссылки на последний элемент в массиве ("Lang, Fritz"), если далее использовать переменную $director , что приведет к непредвиденным последствиям!

Резюме

В данном уроке мы рассмотрели, как использовать конструкцию PHP foreach для организации цикла по элементам массива. Были рассмотрены вопросы:

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

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

На простом языке это будет звучать примерно так:
«Для каждого элемента в указанном массиве выполнить этот код.»

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

PHP Foreach: Пример

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

$employeeAges; $employeeAges["Lisa"] = "28"; $employeeAges["Jack"] = "16"; $employeeAges["Ryan"] = "35"; $employeeAges["Rachel"] = "46"; $employeeAges["Grace"] = "34"; foreach($employeeAges as $key => $value){ echo "Name: $key, Age: $value
"; }

Получаем результат:

Name: Lisa, Age: 28 Name: Jack, Age: 16 Name: Ryan, Age: 35 Name: Rachel, Age: 46 Name: Grace, Age: 34

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

For each синтаксис: $something as $key => $value

Все это безумие примерно переводится в: «Для каждого элемента ассоциативного массива $employeeAges я хочу обратиться к $key и значению в нем, то есть к $value.

Оператор «=>» представляет связь между ключом и значением. В нашем примере мы назвали их как ключ — $key и значение — $value. Тем не менее, было бы легче думать о них, как об имени и возрасте. Ниже в нашем примере мы так и сделаем, и обратите внимание, что результат будет тот же, потому что мы только изменили имена переменных, которые относятся к ключам и значениям.

$employeeAges; $employeeAges["Lisa"] = "28"; $employeeAges["Jack"] = "16"; $employeeAges["Ryan"] = "35"; $employeeAges["Rachel"] = "46"; $employeeAges["Grace"] = "34"; foreach($employeeAges as $name => $age){ echo "Name: $name, Age: $age
"; }

Ну и результат, повторимся, тот же самый.

В недавнем дайджесте интересных ссылок о PHP я обнаружил ссылку на комментарий Никиты Попова на StackOverflow, где он подробно рассказывает о механизме «под капотом» управляющей конструкции foreach.
Поскольку foreach действительно иногда работает более, чем странным образом, я счел полезным сделать перевод этого ответа.

Внимание: этот текст подразумевает наличие базовых знаний о функциональности zval"ов в PHP, в частности вы должны знать что такое refcount и is_ref.
foreach работает с сущностями разных типов: с массивами, с простыми объектами (где перечисляются доступные свойства) и с Traversable -объектами (вернее, объектами, у которых определен внутренний обработчик get_iterator). Здесь мы, в основном, говорим о массивах, но я скажу и об остальных в самом конце.

Прежде чем приступить, пара слов о массивах и их обходе, важная для понимания контекста.

Как работает обход массивов

Массивы в PHP являются упорядоченными хеш-таблицами (элементы хеша объединены в двусвязный список) и foreach обходит массив, следуя указанному порядку.

PHP включает в себя два способа обхода массива:

  • Первый способ - внутренний указатель массива. Этот указатель является частью структуры HashTable и представляет собой просто указатель на текущий элемент хеш-таблицы. Внутренний указатель массива можно безнаказанно изменять, то есть если текущий элемент удалён, внутренний указатель массива будет перемещен на следующий.
  • Второй механизм итерации - внешний указатель массива, под названием HashPosition. Это практически то же самое, что и внутренний указатель массива, но он не является частью HashTable. Этот внешний способ итерации не безопасен к изменениям. Если вы удалите элемент, на который указывает HashPosition, то останетесь с висячим указателем, что приведёт к ошибке сегментации.

Таким образом, внешние указатели массива могут быть использованы только когда вы полностью уверены, что при обходе никакого пользовательского кода выполняться не будет. А такой код может оказаться в самом неожиданном месте, типа обработчика ошибок или деструктора. Вот почему в большинстве случаев PHP приходится использовать внутренний указатель вместо внешнего. Если бы это было иначе, PHP мог бы упасть из-за segmentation fault, как только пользователь начнет делать что-нибудь необычное.

Проблема внутреннего указателя в том, что он является частью HashTable. Так что, когда вы изменяете его, HashTable меняется вместе с ним. И коль скоро обращение к массивам в PHP делается по значению (а не по ссылке), вы вынуждены копировать массив, чтобы в цикле обходить его элементы.

Простой пример, показывающий важность копирования (кстати, не такая большая редкость), это вложенная итерация:

Foreach ($array as $a) { foreach ($array as $b) { // ... } }

Здесь вы хотите чтобы оба цикла были независимым, а не хитро перебрасывались одним указателем.

Итак, мы дошли до foreach.

Обход массива в foreach

Теперь вы знаете, для чего foreach приходится создавать копию массива, прежде чем обойти его. Но это явно не вся история. Сделает PHP копию или нет, зависит от нескольких факторов:

  • Если итерируемый массив является ссылкой, копирования не произойдёт, вместо этого будет выполнен addref:

    $ref =& $array; // $array has is_ref=1 now foreach ($array as $val) { // ... }
    Почему? Потому что любое изменение массива должно распространяться по ссылке, включая внутренний указатель. Если бы foreach сделал копию в этом случае, он бы разрушил семантику ссылки.

  • Если массив имеет refcount=1, копирование, опять таки, не будет выполнено. refcount=1 означает, что массив не используется в другом месте и foreach может использовать его напрямую. Если refcount больше одного, значит массив разделен с другими переменными и для того чтобы избежать изменения, foreach должен скопировать его (независимо от случая ссылки, описанного выше).
  • Если массив обходится по ссылкам (foreach ($array as &$ref)), то - независимо от функции копирования или не-копирования - массив станет ссылкой.

Итак, это первая часть тайны: функция копирования. Вторая часть это то, как текущая итерация выполняется, и она тоже довольно странная. «Обычный» образец итерации, который вы уже знаете (и который часто используется в PHP - отдельно от foreach) выглядит примерно так (псевдокод):

Reset(); while (get_current_data(&data) == SUCCESS) { code(); move_forward(); }
итерация foreach выглядит немного иначе:

Reset(); while (get_current_data(&data) == SUCCESS) { move_forward(); code(); }

Отличие в том, что move_forward() выполняется в начале, а не в конце цикла. Таким образом, когда код пользователя использует элемент $i, внутренний указатель массива уже указывает на элемент $i+1.

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

Последствия для кода

Первое следствие вышеописанного поведения в том, что foreach копирует итерируемый массив в многих случаях (медленно). Но отриньте страх: я пробовал удалить требование копирования и не смог увидеть ускорения работы нигде, кроме искусственных бенчмарков (в которых итерация происходила в два раза быстрее). Похоже, люди просто не итерируют достаточно много.

Второе следствие в том, что обычно не должно быть других следствий. Поведение foreach, в основном, вполне понятно пользователю и просто работает как следует. Вас не должно волновать, как происходит копирование (и происходит ли оно вообще), и в какой конкретно момент времени перемещается указатель.

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

Большую коллекцию поведения в пограничных случаях, которые появляются, когда вы модифицируете массив в ходе итерации, можно найти в тестах PHP. Вы можете начать с этого теста , после чего изменять 012 на 013 в адресе, и так далее. Вы увидите, как поведение foreach будет проявляться в разных ситуациях (всякие комбинации ссылок и.т.д.).

А сейчас вернёмся к вашим примерам:

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 */

Здесь $array имеет refcount=1 до цикла, так что он не будет копирован, но получит addref. Как только вы присвоите значение $array, zval будет разделен, так что массив, к которому вы добавляете элементы и итерируемый массив будут двумя разными массивами.

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 */

Та же ситуация, что и в первом тесте.

// Сдвигаем указатель на единицу, чтобы убедиться, что это не влияет на foreach var_dump(each($array)); foreach ($array as $item) { echo "$item\n"; } var_dump(each($array)); /* Output array(4) { => int(1) ["value"]=> int(1) => int(0) ["key"]=> int(0) } 1 2 3 4 5 bool(false) */

Снова та же история. Во время цикла foreach, у вас refcount=1 и вы получаете только addref, внутренний указатель $array будет изменён. В конце цикла указатель становится NULL (это означает что итерация закончена). each демонстрирует это, возвращая false.

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

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

Но эти примеры недостаточно убедительны. Поведение начинает быть по настоящему непредсказуемым, когда вы используете current в цикле:

Foreach ($array as $val) { var_dump(current($array)); } /* Output: 2 2 2 2 2 */

Здесь вы должны иметь в виду, что current тоже обращается по ссылке, несмотря на то, что не изменяет массив. Это нужно, чтобы согласованно работать со всеми остальными функциями, вроде next, которые обращаются по ссылке (current, вообще-то, предпочтительно-ref функция; она может получить значение, но использует ссылку, если сможет). Ссылка означает, что массив должен быть отделён, следовательно, $array и копия $array, которую использует foreach, будут независимы. Почему вы получаете 2, а не 1, также упомянуто выше: foreach увеличивает указатель массива до начала кода пользователя , а не после. Так что, даже если код все еще работает с первым элементом, foreach уже переместил указатель ко второму.

Теперь попробуем сделать небольшое изменение:

$ref = &$array; foreach ($array as $val) { var_dump(current($array)); } /* Output: 2 3 4 5 false */

Здесь у нас is_ref=1, так что массив не копирован (так как и выше). Но сейчас когда есть is_ref, массив больше не нужно разделять, передавая по ссылке к current. Теперь current и foreach работают с одним массивом. Вы видите массив сдвинутым на единицу как раз из-за того, как foreach обращается с указателем.

То же самое вы увидите, когда будете делать обход массива по ссылкам:

Foreach ($array as &$val) { var_dump(current($array)); } /* Output: 2 3 4 5 false */

Здесь самое важное - то, что foreach назначит нашему $array is_ref=1, когда он будет обходить его в цикле по ссылке, так что получится то же, что и выше.

Еще одна небольшая вариация, здесь мы присвоим наш массив еще одной переменной:

$foo = $array; foreach ($array as $val) { var_dump(current($array)); } /* Output: 1 1 1 1 1 */

Здесь refcount массива $array принимает значение 2, когда цикл начался, так что нужно сделать копию, прежде чем начинать. Таким образом, $array и массив используемый foreach будут разными с самого начала. Вот почему вы получаете ту позицию внутреннего указателя массива, которая была актуальна до начала цикла (в этом случае он был в первой позиции).

Итерация объектов

При итерации объектов имеет смысл рассмотреть два случая:

Объект не Traversable (вернее, не определен внутренний обработчик get_iterator)

В этом случае итерация происходит почти так же, как у массивов. Та же семантика копирования. Единственное отличие: foreach запустит некий дополнительный код, чтобы пропустить свойства, недоступные в текущей области видимости. Еще пара интересных фактов:

  • Для объявленных свойств PHP реоптимизирует хеш-таблицу свойств. Если вы все-таки итерируете объект, он должен реконструировать эту хеш-таблицу (что повышает использование памяти). Не то, чтобы вам следовало беспокоиться об этом, просто имейте в виду.
  • На каждой итерации хеш-таблица свойств будет получена заново, то есть PHP будет вызывать get_properties снова, и снова, и снова. Для «обычных» свойств это не так важно, но если свойства создаются динамически (это часто делают встроенные классы) - то таблица свойств будет пересчитываться каждый раз.
Объект Traversable

В этом случае всё, что сказано выше, не будет применяться никоим образом. Также PHP не будет копировать и не будет применять никакие трюки вроде увеличения указателя до прохода цикла. Я думаю что режим прохода по обходимому (Traversable) объекту куда более предсказуем и не требует дальнейшего описания.

Замена итерируемого объекта во время цикла

Другой необычный случай, который я не упомянул - PHP допускает возможность замены итерируемого объекта во время цикла. Вы можете начать с одним массивом и продолжить, заменив его на полдороге другим. Или начать с массивом, в затем заменить его объектом:

$arr = ; $obj = (object) ; $ref =& $arr; foreach ($ref as $val) { echo "$val\n"; if ($val == 3) { $ref = $obj; } } /* Output: 1 2 3 6 7 8 9 10 */

Как видите, PHP просто начал обходить другую сущность, как только произошла замена.

Изменение внутреннего указателя массива во время итерации

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

Тут вы можете получить не то, что ожидали: если вызывать next или prev в теле цикла (в случае передачи по ссылке), вы увидите, что внутренний указатель переместился, но это никак не повлияло на поведение итератора. Причина в том, что foreach делает бекап текущей позиции и хеша текущего элемента в HashPointer после каждого прохода цикла. На следующей проходе foreach проверит, не менялась ли позиция внутреннего указателя и попытается восстановить ее, используя этот хеш.

Давайте посмотрим что означает «попытается». Первый пример показывает, как изменение внутреннего указателя не меняет режим foreach:

$array = ; $ref =& $array; foreach ($array as $value) { var_dump($value); reset($array); } // output: 1, 2, 3, 4, 5

Теперь давайте попробуем сделать unset элементу, к которому обратится foreach при первом проходе (ключ 1):

$array = ; $ref =& $array; foreach ($array as $value) { var_dump($value); unset($array); reset($array); } // output: 1, 1, 3, 4, 5

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

Имейте в виду, хеш - всего лишь хеш. Случаются коллизии. Попробуем теперь так:

$array = ["EzEz" => 1, "EzFY" => 2, "FYEz" => 3]; $ref =& $array; foreach ($array as $value) { unset($array["EzFY"]); $array["FYFZ"] = 4; reset($array); var_dump($value); } // output: 1 1 3 4

Работает так, как мы и ожидали. Мы удалили ключ EzFY (тот, где как раз был foreach), так что был сделан сброс. Также мы добавили дополнительный ключ, поэтому в конце мы видим 4.

И вот тут приходит неведомое. Что произойдёт, если заменить ключ FYFY с FYFZ? Давайте попробуем:

$array = ["EzEz" => 1, "EzFY" => 2, "FYEz" => 3]; $ref =& $array; foreach ($array as $value) { unset($array["EzFY"]); $array["FYFY"] = 4; reset($array); var_dump($value); } // output: 1 4

Сейчас цикл перешёл непосредственно к новому элементу, пропуская всё остальное. Это потому что ключ FYFY имеет коллизию с EzFY (вообще-то, все ключи из этого массива тоже). Более этого, элемент FYFY находится по тому же адресу в памяти, что и элемент EzFY который только что был удален. Так что для PHP это будет та же самая позиция с тем же хешом. Позиция «восстановлена» и происходит переход к концу массива.

Цикл PHP foreach можно использовать следующим образом:

foreach($array_name as $value){ //код, который должен выполняться }

foreach($array_name as $key =>$value){ // //код, который должен выполняться }

Пример использования цикла foreach с числовым массивом

В этом примере мы создадим массив из пяти элементов с числовыми значениями. После этого цикл PHP foreach будет использован для выполнения итерации этого массива. Внутри цикла foreach мы использовали echo , чтобы вывести значения массива:

Посмотреть демо-версию и код

Пример с ключами и значениями массива

В этом примере описан другой способ использования цикла foreach PHP . Для этого мы создали ассоциативный массив из трех элементов. В него входят имена сотрудников (в качестве ключей ) и суммы заработной платы (в качестве значений ):

Посмотреть демо-версию и код

Пример изменения значения элемента массива в цикле foreach

Также можно c помощью PHP array foreach можно изменять значения элементов массива. Для этого используется «& » перед «$ » для переменной значения. Например:

&$value_of_element

Значение будет изменено. Чтобы вам было понятнее, рассмотрим следующий пример.

В этом примере мы создали числовой массив из пяти элементов. После этого использовали цикл foreach для отображения значений элементов.

Затем создали еще один цикл foreach , где перед $value_of_element добавляется «& «. Внутри фигурных скобок присваиваем новые значения элементам массива.

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

Посмотреть демо-версию и код

Для чего используется цикл PHP foreach?

Цикл PHP foreach используется для работы с массивом. Он перебирает каждый его элемент.

Также можно использовать для работы с массивами цикл for . Например, используя свойство length , чтобы получить длину массива, а затем применить его в качестве оператора max . Но foreach делает это проще, так как он предназначен для работы с массивами.

Если вы работаете с MySQL , то для этого данный цикл подходит еще больше. Например, можно выбрать несколько строк из таблицы БД и передать их в массив. После этого, используя цикл foreach , перебрать все элементы массива с выполнением какого-либо действия.

Обратите внимание, что можно использовать цикл foreach с массивом или только с объектом.

Применение цикла foreach

В PHP существует два способа использования цикла foreach PHP. Оба описаны ниже.

  • Синтаксис первого метода использования:

foreach($array_name as $value){ echo $value }

При этом нужно указать имя массива, а затем переменную $value .

Для каждой итерации значение текущего элемента присваивается переменной $value . После завершения итерации переменной присваивается значение следующего элемента. И так до тех пор, пока все элементы массива не будут перебраны.

  • Синтаксис второго метода (PHP foreach as key value ):

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

Во время выполнения каждой итерации значение текущего элемента будет присвоено переменной $value_of_element. Кроме этого ключ элемента присваивается переменной $key_of_element.

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

Данная публикация представляет собой перевод статьи «PHP foreach loop 2 ways to use it » , подготовленной дружной командой проекта