Цикл 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 » , подготовленной дружной командой проекта