PHP 8.6.0 Beta 1 is available for testing

foreach

(PHP 4, PHP 5, PHP 7, PHP 8)

Языковой конструкцией foreach удобно перебирать массивы (array ) и объекты, классы которых реализуют интерфейс Traversable . Конструкция foreach выдаст ошибку при попытке перебора переменной с другим типом данных или неинициализированной переменной. Разработчику доступны два вида синтаксиса:

Конструкция foreach умеет получать ключ каждого элемента, если требуется, и присваивать значение ключа переменной key:

foreach (iterable_expression as $value) {
 statement_list
}
foreach (iterable_expression as $key => $value) {
 statement_list
}

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

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

Обратите внимание, что конструкция foreach не изменяет внутренний указатель массива, с которым, например, работают функции current() и key() .

Разработчику доступна настройка итерации объектов.

Пример #1 Базовая работа с конструкцией foreach

<?php
/* Пример перебора только значений */
$array = [1, 2, 3, 17];
foreach ($array as $value) {
 echo "Значение текущего элемента массива \$array: $value.\n";
}
/* Пример перебора ключей и значений */
$array = [
 "one" => 1,
 "two" => 2,
 "three" => 3,
 "seventeen" => 17
];
foreach ($array as $key => $value) {
 echo "Ключ: $key => Значение: $value\n";
}
/* Пример итерации по ключам и значениям многомерного массива */
$grid = [];
$grid[0][0] = "a";
$grid[0][1] = "b";
$grid[1][0] = "y";
$grid[1][1] = "z";
foreach ($grid as $y => $row) {
 foreach ($row as $x => $value) {
 echo "Значение на позиции x=$x и y=$y: $value\n";
 }
}
/* Пример итерации по динамическому массиву */
foreach (range(1, 5) as $value) {
 echo "$value\n";
}
?>

Замечание:

Конструкция foreach не поддерживает подавление сообщений об ошибках оператором @.

Распаковка вложенных массивов

(PHP 5 >= 5.5.0, PHP 7, PHP 8)

В PHP доступна итерация по массиву массивов и распаковка вложенного массива в переменные цикла. Массив распаковывают либо путём деструктуризации массива через конструкцию [], либо указывают языковую конструкцию list() как значение цикла.

Замечание: Деструктуризация массивов через конструкцию [] возможна только с PHP 7.1.0

В обоих следующих примерах переменной $a присваивается первый элемент вложенного массива, а переменная $b получит второй элемент:

<?php
$array = [
 [1, 2],
 [3, 4],
];
foreach ($array as [$a, $b]) {
 echo "A: $a; B: $b\n";
}
foreach ($array as list($a, $b)) {
 echo "A: $a; B: $b\n";
}
?>

Результат выполнения приведённого примера:

A: 1; B: 2
A: 3; B: 4

Распаковка проигнорирует оставшиеся элементы, если в значении цикла указали меньшее переменных, чем элементов в массиве. Аналогично элементы пропускают, оставляя только запятую:

<?php
$array = [
 [1, 2, 5],
 [3, 4, 6],
];
foreach ($array as [$a, $b]) {
 // Обратите внимание, переменную $c не указали
 echo "$a$b\n";
}
foreach ($array as [, , $c]) {
 // Пропускаем переменные $a и $b
 echo "$c\n";
}
?>

Результат выполнения приведённого примера:

1 2
3 4
5
6

При недостаточном количестве элементов для заполнения переменных в конструкции list() или конструкции с квадратными скобками генерируется уведомление:

<?php
$array = [
 [1, 2],
 [3, 4],
];
foreach ($array as [$a, $b, $c]) {
 echo "A: $a; B: $b; C: $c\n";
}
?>

Результат выполнения приведённого примера:

Notice: Undefined offset: 2 in example.php on line 7
A: 1; B: 2; C:
Notice: Undefined offset: 2 in example.php on line 7
A: 3; B: 4; C:

Конструкция foreach и ссылки

Элементы массива возможно напрямую модифицировать внутри цикла путём указания перед значением $value знака &, тогда значение присваивается по ссылке.

<?php
$arr = [1, 2, 3, 4];
foreach ($arr as &$value) {
 $value = $value * 2;
}
// Массив $arr теперь содержит значения [2, 4, 6, 8]
unset($value); // Разрываем ссылочную связь с последним элементом
?>

Внимание

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

<?php
$arr = [1, 2, 3, 4];
foreach ($arr as &$value) {
 $value = $value * 2;
}
// Массив $arr теперь содержит значения [2, 4, 6, 8]
// Без уничтожения ссылки конструкцией unset($value) переменная $value по-прежнему ссылается на последний элемент: $arr[3]
foreach ($arr as $key => $value) {
 // Элемент $arr[3] обновляется с каждым значением массива $arr...
 echo "{$key} => {$value} ";
 print_r($arr);
}
// ...пока предпоследнее значение не скопируется в последнее
?>

Результат выполнения приведённого примера:

0 => 2 Array ( [0] => 2, [1] => 4, [2] => 6, [3] => 2 )
1 => 4 Array ( [0] => 2, [1] => 4, [2] => 6, [3] => 4 )
2 => 6 Array ( [0] => 2, [1] => 4, [2] => 6, [3] => 6 )
3 => 6 Array ( [0] => 2, [1] => 4, [2] => 6, [3] => 6 )

Пример #2 Итерация по значениям константного массива по ссылке

<?php
foreach ([1, 2, 3, 4] as &$value) {
 $value = $value * 2;
}
?>

Смотрите также

Нашли ошибку?

ИнструкцияИсправлениеСообщение об ошибке
+Добавить

Примечания пользователей 5 notes

up
45
Okafor Chiagozie
3 years ago
An easier way to unpack nested array elements
$array = [
 [1, 2],
 [3, 4],
];
foreach ($array as [$a, $b]) {
 echo "A: $a; B: $b\n";
}
up
2
mohammed dot abdulaziz dot business at gmail dot com
5 months ago
The following C code mimics the reference leak behavior of a by-reference foreach loop in PHP. By intentionally leaving current pointing to the last element after the first loop, we can reproduce the same silent array corruption that occurs in PHP.
#include <stdio.h>
int main()
{
 int arr[] = {1, 2, 3, 4};
 int *current;
 //First Loop doubles the array
 for (size_t i = 0; i < sizeof(arr) / sizeof(arr[0]); i++)
 {
 //arr[i] === *(arr + i)
 arr[i] *= 2;
 current = arr + i;
 printf("Current modified:%d\n", *current);
 }
 /*
 After the loop completes, the arr is now {2,4,6,8}. 
 As for current, it is going to have the memory location of the last element (memory location of 8).
 */
 for (size_t i = 0; i < sizeof(arr) / sizeof(arr[0]); i++)
 {
 /*
 In each iteration, the memory location of 8 is going to be dereferenced and set to arr[i].
 As a result, the last value will be equal to the value before it
 */
 *current = arr[i];
 printf("Current:%d\n", *current);
 }
 return 0;
}
Just as PHP's $value remains a reference to the last element after a by-reference foreach, current here remains a pointer to arr[3]. Every iteration of the second loop writes into arr[3], ultimately copying the second-to-last value onto the last element.
up
1
sunfundev at gmail dot com
9 months ago
Definitely relevant for PHP 7+
1. You can't change array during iteration
Foreach WILL NOT LOOP through new values added to the array 
<?php
while inside the loop.
$a = [1, 2, 3];
foreach ($a as $k => $v) {
 echo $v;
 if ($v === 2) {
 $v[] = 4;
 }
}
?>
Output: 123
But the original array was modified: [1, 2, 3, 4]
Foreach WILL LOOP through values deleted from the array while inside the loop.
<?php
$a = [1, 2, 3];
foreach ($a as $k => $v) {
 echo $v;
 if ($v === 2) {
 unset($a[2]);
 }
}
?>
Output: 123
But the original array was modified: [1, 2]
2. But If you iterate by reference using foreach ($arr as &$v) then $arr is turned into a reference and you can change it during iteration
Foreach WILL LOOP through new values added to the array while inside the loop.
<?php
$a = [1, 2, 3];
foreach ($v as &$v) {
 echo $v;
 if ($v === 2) {
 $v[] = 4;
 }
}
?>
Output: 1234
Foreach WILL NOT LOOP through values deleted from the array while inside the loop.
<?php
$a = [1, 2, 3];
foreach ($a as $k => &$v) {
 echo $v;
 if ($v === 2) {
 unset($a[2]);
 }
}
?>
Output: 12
up
5
renatoaraujoleal at gmail dot com
1 year ago
<?php
$array = [
 [1, 2, 3],
 [3, 4, 6],
];
foreach ($array as [$a, $b]) {
 // Observe que não existe $c aqui.
 echo "$a$b\n";
}
foreach ($array as [, , $c]) {
 // Pulando $a e $b
 echo "$c\n";
}
?>

I would like to correct this example above!
The answer of this algorithm is:
1 2
3 4
3
6
up
-1
harl at gmail dot com
8 months ago
As well as numerically-indexed arrays, nested associative arrays can also be unnested in the foreach()
<?php
$records = [
 ['name' => 'Alice', 'address' => '...'],
 ['name' => 'Bob', 'address' => '...'],
 ['name' => 'Chris', 'address' => '...'],
 ...];
foreach($records as ['name' => $name]) {
 echo "$name\n";
}
foreach($records as ['address' => $address, 'name' => $name]) {
 echo "$name @ $address\n";
}
?>

The usual warnings about undefined array keys will occur if any of the element arrays lack the requested key.
One additional detail, the key is still just an ordinary string-valued expression, so...
<?php
$field = 'address';
foreach($records as [$field => $value]) {
 echo "$value\n";
}
?>
If the value of $field changed within the loop, the new field would be accessed in subsequent iterations.
+Добавить

AltStyle によって変換されたページ (->オリジナル) /