## 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;
    }

    ?>

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

- array
- Traversable
- iterable
- list()

`↑` and `↓` to navigate • `Enter` to select • `Esc` to close • `/` to open