Ошибка передачи PHP по ссылке?

Не переходите по ссылке. Я знаю, но.

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

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

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

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

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

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

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

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

<?php


$array = ["one", "two", "three"];
$other_array = [];
echo "<pre>";
print_r($array);
echo "</pre>";

foreach($array as &$reference){
  if($reference == "one") $reference = "one_changed";
}

echo "<pre>";
print_r($array);
echo "</pre>";

foreach($array as $reference){
  array_push($other_array, $reference);
}
echo "====changed them but did not push onto array====<br>";

echo "====changed also====";
echo "<pre>";
print_r($array);
echo "</pre>";
echo "====changed also====";
echo "<pre>";
print_r($other_array);
echo "</pre>";

person I'm Root James    schedule 23.06.2019    source источник


Ответы (2)


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

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
)

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

person alx    schedule 23.06.2019

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

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

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

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

person newacct    schedule 29.06.2019