Подтвердить что ты не робот

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

PHP 7 Документ о возвращении несовместимых изменений сообщает следующее о foreach:

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

Я пытаюсь понять, что это значит, и мой главный вопрос: будет ли этот код работать так же в PHP 7, как это происходит в PHP 5.6?

foreach($array as $elementKey => $element) {
    if ($element == 'x') {
        unset($array[$elementKey]);
    }
}

Мои два вопроса:

  • Будет ли этот код работать?

  • Если да, можете ли вы объяснить (может быть, на примере), что означает это новое изменение в PHP 7?

Edit

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

$array = ['x', 'y', 'z'];

$new = [];

foreach($array as $element) {
    if ($element == 'x') {
        $array[2] = 'a';
    }

    $new[] = $element;
}

print_r($new);

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

Я понимаю, что если я сделаю это по ссылке, я получу a в новом. В противном случае я этого не сделаю. Но в обеих версиях это выглядит так.

Мне действительно нужно знать , что такое несовместимость (на примере)?

Изменить 2

Ссылка предложенная в @NikiC, содержит остальную часть истории, которую я искал:

В большинстве случаев это изменение прозрачно и не имеет другого эффекта, чем лучшая производительность. Однако есть один случай, когда это приводит к разному поведению, а именно к случаю, когда массив был ссылкой заранее:

$array = [1, 2, 3, 4, 5];
$ref = &$array;
foreach ($array as $val) {
    var_dump($val);
    $array[2] = 0;
}
/* Old output: 1, 2, 0, 4, 5 */
/* New output: 1, 2, 3, 4, 5 */

Раньше итерация ссылочных массивов по значению была специальными случаями. В этом случае дублирование не произошло, поэтому все изменения массива во время итерации будут отражены в цикле. В PHP 7 этот частный случай ушел: Итерация по байтам по значению всегда будет работать над исходными элементами, не обращая внимания на какие-либо изменения во время цикла.

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

4b9b3361

Ответ 1

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

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

<?php
$array = ['x', 'y', 'z'];

foreach($array as $elementKey => $element) {
    if ($element=='x') {
        unset($array[$elementKey]);
    }
}

var_dump($array); // lists 'y' and 'z'

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

<?php
$array = ['x', 'y', 'z'];

foreach($array as $element) {
    if ($element=='x') {
        $element = 'a';
    }
}

var_dump($array); // 'x', 'y', 'z'

Vs по ссылке, где мы объявляем $element ссылкой на элемент массива:

<?php
$array = ['x', 'y', 'z'];

foreach($array as &$element) {
    if ($element=='x') {
        $element = 'a';
    }
}

var_dump($array); // 'a', 'y', 'z'

Здесь приведен пример этого кода для различных версий PHP.