Почему PHP перезаписывает значения, когда я повторяю этот массив дважды (посредством ссылки по значению)
Вопрос
Если я повторяю через массив дважды, один раз в качестве ссылки, а затем по значению, PHP будет перезаписать последнее значение в массиве, если я использую то же имя переменной для каждого цикла. Это лучше всего проиллюстрировано через пример:
$array = range(1,5);
foreach($array as &$element)
{
$element *= 2;
}
print_r($array);
foreach($array as $element) { }
print_r($array);
Выход:
Массив ([0] => 2 [1] => 4 [2] => 6 [3] => 8 [4] => 10 )
Массив ([0] => 2 [1] => 4 [2] => 6 [3] => 8 [4] => 8 )
Обратите внимание, что я не ищу исправления, я хочу понять, почему это происходит. Также обратите внимание, что не происходит, если имена переменной в каждом цикле не вызываются $element
, поэтому я предполагаю, что это связано с $element
Все еще находиться в области применения и ссылку после окончания первого цикла.
Решение
После первой петли $ элемент по-прежнему является ссылкой на последний элемент / значение $ Array.
Вы можете увидеть, что при использовании var_dump () вместо print_r ()
array(5) {
[0]=>
int(2)
...
[4]=>
&int(2)
}
Обратите внимание, что и в &int(2)
.
Со второй петлей вы назначаете значения для $ элемента. И поскольку это все еще ссылка, стоимость в массиве тоже меняется. Попробуйте это с
foreach($array as $element)
{
var_dump($array);
}
как вторая петля, и вы увидите.
Так что это более или менее то же самое, что
$array = range(1,5);
$element = &$array[4];
$element = $array[3];
// and $element = $array[4];
echo $array[4];
(Только с петлями и умножением ... Эй, я сказал «более или менее» ;-))
Другие советы
Вот объяснение самого человека:
$y = "some test"; foreach ($myarray as $y) { print "$y\n"; }
Здесь
$y
является записью таблицы символов, ссылаясь на строку, содержащую «какой-то тест». На первой итерации вы по сути делаете:$y = $myarray[0]; // Not necessarily 0, just the 1st element
Так что теперь хранение, связанное с
$y
перезаписан ценностью от$myarray
. Отказ Если$y
Ассоциируется с каким-либо другим хранением через ссылку, что хранение будет изменено.Теперь скажем, что вы сделаете это:
$myarray = array("Test"); $a = "A string"; $y = &$a; foreach ($myarray as $y) { print "$y\n"; }
Здесь
$y
связан с тем же хранилищем, что и$a
через ссылку, поэтому, когда делает первую итерацию:$y = $myarray[0];
Единственное место, где «тестовая» строка может идти, находится в хранилище, связанное с
$y
.
Вот как вы решили эту проблему:
foreach($array as &$element)
{
$element *= 2;
}
unset($element); #gets rid of the reference and cleans the var for re-use.
foreach($array as $element) { }