Добавление ссылок в PHP в массив создает массив ссылок

Не уверен, если это считается ошибкой

$array = ['numbers' => [1, 2, 3]];
foreach ($array as &$numbers) {
$numbers = [4, 5, 6];
}
var_dump($array);
modify_array($array);
var_dump($array);

function modify_array($array_arg)
{
$array_arg['numbers'] = [1, 2, 3];
}

Печать

array(1) {
["numbers"]=>
&array(3) {
[0]=>
int(4)
[1]=>
int(5)
[2]=>
int(6)
}
}
array(1) {
["numbers"]=>
&array(3) {
[0]=>
int(1)
[1]=>
int(2)
[2]=>
int(3)
}
}

Обратите внимание, что $ array не был передан по ссылке на modify_array (), однако вложенный массив был изменен. Звучит логично, но не уверен, что это задокументировано!

7

Решение

Если вы используете foreah со ссылкой, вы запрещаете PHP делать копию массива, поэтому вы работаете с оригинальным массивом. Когда вы закончите цикл foreach, вы должны unset() переменная используется в цикле, потому что она все еще остается в памяти. Если вы этого не сделаете, вы получите непредсказуемые результаты, подобные представленным в вашем вопросе. Даже в документация у вас есть предупреждение:

Предупреждение Ссылка $ значение и последний элемент массива остается даже после для каждого петля. Рекомендуется уничтожить его
снята с охраны ().

Вот Вы можете найти действительно хорошие примеры циклов foreach без сброса.

Так что, если вы добавите unset()все выглядит как надо

$array = ['numbers' => [1, 2, 3]];
foreach ($array as &$numbers) {
$numbers = [4, 5, 6];
}
unset($numbers);
var_dump($array);
modify_array($array);
var_dump($array);

function modify_array($array_arg) {
$array_arg['numbers'] = [1, 2, 3];
}

Результат:

array(1) { ["numbers"]=> array(3) { [0]=> int(4) [1]=> int(5) [2]=> int(6) } }
array(1) { ["numbers"]=> array(3) { [0]=> int(4) [1]=> int(5) [2]=> int(6) } }
4

Другие решения

Если вы перепишите следующий код:

foreach ($array as &$numbers) {
$numbers = [4, 5, 6];
}

Что-то вроде этого:

  $array['numbers'] = &$array['numbers'];
$array['numbers'] = [4,5,6];

Такое поведение будет легче понять, и это, кажется, известная проблема.
(Увидеть: http://php.net/manual/en/language.references.php#87532)

0