PHP цикл foreach не обновляет значение - PullRequest
0 голосов
/ 04 марта 2019

Если показанная ниже программа PHP хранится в файле bug.php, то эта команда

php bug.php

будет выдавать этот вывод при использовании PHP 7.0.33-0ubuntu0.16.04.1 (cli) (NTS)Zend Engine v3.0.0, Copyright (c) 1998-2017 Zend Technologies с Zend OPcache v7.0.33-0ubuntu0.16.04.1, Copyright (c) 1999-2017, Zend Technologies

Вывод:

Initial array
Array
(
    [0] => aa
    [1] => bb
)
j = 0  line = aa
element 0 is aa

j = 1  line = bb    <----------------------------------------------
element 1 is ***bb  <----------------------------------------------

Final array
Array
(
    [0] => aa
    [1] => ***bb
)

Обратите внимание на отмеченные строки выше.Элемент $ A [1] равен "*** bb", а $ line - который foreach должен ассоциировать с ключом 1 - это "bb".

Это ошибка или есть какая-то тонкость PHP Iне в курсе?

<?php

    $A = array
    (
    "aa",
    "bb",
    );

    echo "Initial array\n";
    print_r($A);

    foreach ($A as $j => $line)
    {
        echo "j = $j  line = $line\n";
        echo "element $j is {$A[$j]}\n\n";

        if ($j == 0)
            $A[1] = "***" . $A[1];
    }

    echo "Final array\n";
    print_r($A);

?>

Ответы [ 3 ]

0 голосов
/ 04 марта 2019

Как упомянуто в примечаниях к php.net, если на массив не есть ссылка foreach работает с копией указанного массива, а не с самим массивом.Вы выводите переменную из оригинальной копии, а затем из измененного массива.

0 голосов
/ 05 марта 2019

Массив передается в foreach как копия - , если вы не передадите его в качестве ссылки (укажите, что, добавив & к $value) , он не будетотражают обновления значения, которое вы делаете в первой итерации.

Учтите это:

foreach ($A as $j => &$line)
{
    echo "j = $j  line = $line\n";
    echo "element $j is {$A[$j]}\n\n";

    if ($j == 0)
       $A[1] = "***" . $A[1];
}
/* Will output:

 * j = 0  line = aa
 * element 0 is aa
 *
 * j = 1  line = ***bb
 * element 1 is ***bb
 */

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

Надеюсь, что все ясно ...

Я заметил, что в документах написано, что именно:

В документации точно сказано:)

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

0 голосов
/ 04 марта 2019

Если на массив не ссылаются, foreach() работает с копией указанного массива, а не с самим массивом.У foreach есть некоторые побочные эффекты на указатель массива.Не полагайтесь на указатель массива во время или после foreach, не сбрасывая его.

Таким образом, когда вы изменяете $A[1], вы вносите изменения в массив оригинал , а не copy , который впоследствии использует цикл foreach().

Это важное различие в настоящее время отсутствует в официальной документации , но вы можете прочитать об этом здесь: Как на самом деле работает PHP 'foreach'?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...