グローバル変数の連想配列変数($GLOBALS)を代入した変数の値を変更すると、$GLOBALS にまで反映されるんですが、PHP8.1.0 からできなくなりました。
え? そんなことできてたの? と思った人もいるでしょう。
むしろ、PHP8.1ではまともになったじゃんって思う。
普通の連想配列では、代入した変数値を変更すると元の変数配列には変更されません。代入する側の変数とされる側の変数は代入したときの値は同じでも全く別物だから。
(値のコピー。)
でも $GLOBALS ではちがいました。
<?php
$g_test = 'sample';
$globals = $GLOBALS;
$globals['g_test'] = 'change';
echo 'globals value: ' . $globals['g_test'] . PHP_EOL;
echo 'GLOBALS value: ' . $GLOBALS['g_test'] . PHP_EOL;
globals value: change
GLOBALS value: change
globals value: change
GLOBALS value: sample
普通、イコール(=)での代入は左辺変数へのコピーで左右は独立しています。むしろPHP8.1での変更は他の連想配列と同じ動きになるで分かりやすくなりました。
というか、なんで $GLOBALS はこうなってたんだろう。
PHP公式のリファレンスでも不思議な記述があります。
// PHP 8.1.0 より前の振る舞い
$a = 1;
$globals = $GLOBALS; // 建前上は値渡しのコピー
$globals['a'] = 2;
var_dump($a); // int(2)
(『建前上は』って...。意味深な内容。)
$GLOBALS はリファレンスではありません。動きとしてはクラスのオブジェクトに近い。(内部の仕組みはどうなってるか分からない。)
PHP8.1は2021年11月25日にリリースされたばかりなので、この不思議な動きをするバージョンを使ってる人は多いと思います。
気をつけましょう。
ちなみにPHP8.1で同じようなことはできません。$GLOBALS のリファレンス作成はPHP8.1からエラーになるから。
そもそも、$g_test で変更すればいいじゃんという話です。(ローカルスコープなら global $g_test)
PHP公式ドキュメント