PHP мимо ссылки ошибка? - PullRequest
1 голос
/ 23 июня 2019

Не передавайте по ссылке. Я знаю ..... но.

Кто-нибудь может объяснить, что здесь происходит? Я попытаюсь объяснить, что я думаю, и, возможно, это ошибка PHP.

Сценарий кода ниже показывает пример, где массив строк передается по ссылке (я не знаю ...), и строка изменяется, если равна флагу.

Массив выходит из этого цикла foreach без изменений. Строка была изменена по желанию. Все остальные значения все еще находятся в массиве.

Я передаю измененный массив не по ссылке в другой цикл foreach и пытаюсь просто перенести значения в другой массив ($other_array), используя то же имя переменной, что и в первом цикле. Я предполагаю, что имя переменной будет сброшено на новое значение (аналогично $ variable = "new value"). Однако, похоже, что имя переменной не разыменовано.

Каким-то образом в этом цикле исходный массив изменяется и выходит с повторным вторым последним значением и пропускает исходное последнее значение. Это всегда верно для других случаев с более длинными и более сложными массивами.

Код ниже, чтобы кто-то мог это проверить.

1) Является ли это ошибкой PHP, что переменная не разыменовывается при использовании во втором цикле foreach?

2) Если кто-то может предоставить информацию о том, что может происходить под капотом PHP в терминах ссылок на переменные, я был бы рад понять. Другими словами, почему foreach вызывает дубликат и отсутствующий элемент в массиве?

<code><?php


$array = ["one", "two", "three"];
$other_array = [];
echo "<pre>";
print_r($array);
echo "
"; foreach ($ массив как & $ reference) { if ($ reference == "one") $ reference = "one_changed"; } echo "
";
print_r($array);
echo "
"; foreach ($ array как $ reference) { array_push ($ other_array, $ reference); } echo "==== изменил их, но не выдвинул массив ====
"; echo "==== изменилось также ===="; echo "
";
print_r($array);
echo "
"; echo "==== изменилось также ===="; echo "
";
print_r($other_array);
echo "
";

Ответы [ 2 ]

2 голосов
/ 23 июня 2019

Не ошибка, если вы хотите повторно использовать переменную, ранее использовавшуюся как ссылку, вам нужно сделать следующее:

unset($var);

В частности, добавив эту строку после первого цикла:

foreach($array as &$reference){
  if($reference == "one") $reference = "one_changed";
}
unset($reference); // <--- this

Решает все проблемы:

Array
(
    [0] => one
    [1] => two
    [2] => three
)
Array
(
    [0] => one_changed
    [1] => two
    [2] => three
)
====changed them but did not push onto array====<br>====changed also====Array
(
    [0] => one_changed
    [1] => two
    [2] => three
)
====changed also====Array
(
    [0] => one_changed
    [1] => two
    [2] => three
)

И еще одна вещь.Элементы массива также могут быть ссылками, например:

$a = 1;

$c=[];
$c[0] =& $a;
$c[1] =& $a;
print_r($c);

$a=2;
print_r($c);

Это выведет:

Array
(
    [0] => 1
    [1] => 1
)
Array
(
    [0] => 2
    [1] => 2
)

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

0 голосов
/ 29 июня 2019

Это не «передача по ссылке», поскольку здесь нет передачи.

Изменение элементов массива в цикле foreach с помощью & описано на странице руководства PHP на foreach , с предупреждением о необходимости сброса переменной впоследствии.

Предупреждение

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

...