Почему 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 все еще находящимся в области видимости, и ссылкой после окончания первого цикла.

После того, как первый элемент цикла $ по-прежнему является ссылкой на последний элемент / значение массива $.
Вы можете видеть, что при использовании var_dump () вместо print_r ()

 array(5) { [0]=> int(2) ... [4]=> &int(2) } 

Обратите внимание, что & in &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) { } с foreach($array as &$element) { $element *= 2; } unset($element); #gets rid of the reference and cleans the var for re-use. foreach($array as $element) { }