TL; DR Если вы используете PHP 7, массив не будет скопирован внутри, если вы его не измените.Это называется копирование при записи .
Чтобы понять, как работает PHP под капотом, вы можете прочитать Основы подсчета ссылок :
Переменная PHP хранится в контейнере, называемом "zval".
PHP достаточно умен, чтобы не копировать реальный контейнер переменных, когда в этом нет необходимости.
Давайте попробуем проиллюстрировать это на вашем упрощенном примере, используя debug_zval_dump
:
$array = [
'lvl1' => [
'lvl2' => [
'lvl3' => [
],
],
],
];
$path = ['lvl1', 'lvl2', 'lvl3'];
$tmp = $array;
foreach ($path as $lvl) {
debug_zval_dump($array);
$tmp = $tmp[$lvl];
}
debug_zval_dump($array);
Если вы запустите этот код, вы получите следующий вывод:
array(1) refcount(4){
["lvl1"]=>
array(1) refcount(1){
["lvl2"]=>
array(1) refcount(1){
["lvl3"]=>
array(0) refcount(1){
}
}
}
}
array(1) refcount(3){
["lvl1"]=>
array(1) refcount(2){
["lvl2"]=>
array(1) refcount(1){
["lvl3"]=>
array(0) refcount(1){
}
}
}
}
array(1) refcount(3){
["lvl1"]=>
array(1) refcount(1){
["lvl2"]=>
array(1) refcount(2){
["lvl3"]=>
array(0) refcount(1){
}
}
}
}
array(1) refcount(3){
["lvl1"]=>
array(1) refcount(1){
["lvl2"]=>
array(1) refcount(1){
["lvl3"]=>
array(0) refcount(2){
}
}
}
}
Обратите внимание на refcount
: он меняется, поэтому внутренне PHP назначается по ссылке, пока вы фактически не измените назначенное значение.Вы можете прочитать об этом в сообщении в блоге от nikic :
Важным отличием от PHP 5 является то, что все переменные могли совместно использовать один и тот же массив, хотя некоторые из них были PHPссылки и некоторые не были.Только после выполнения какой-либо модификации массив будет разделен.