ツイート
シェア
LINEで送る
B! はてぶでブックマーク
Pocketでブックマーク
RSSフィード

PHP, $GLOBALS の変数への代入は参照型? まるでクラスオブジェクトのような動き。

php
イラストダウンロードサイト【イラストAC】
の画像をもとに加工しています。

PHPのグローバル変数を一括管理している変数に $GLOBALS がありますが、普通の連想配列とはちがう動きをします。

変数に代入するとコピーではなくリファレンスやクラスオブジェクトの代入ように動く。

'=&' ではなく '=' でなるのが不思議。

$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 だけはちがいます。これはまるでリファレンスのような動き。

PHP公式ドキュメントでも意味深な記述があります。

// PHP 8.1.0 より前の振る舞い
$a = 1;
$globals = $GLOBALS; // 建前上は値渡しのコピー
$globals['a'] = 2;
var_dump($a); // int(2)

『建前上は』ってなんですか? 実際は違う動きをするのが見え隠れする。公式リファレンスなんだからはっきりして欲しい。

でもリファレンスじゃない。'=&' を使って代入できるから。かといってクラスオブジェクトの代入とも違う。

$globals =& $GLOBALS;

というコーディングは可能だが無意味。

= でもリファレンスと同じ動きをするから。

クラスオブジェクトはオブジェクト指向の仕様に基づいているので連想配列で使ってるとは思えない。

オブジェクトの代入はオブジェクトIDだけをコピーしていて、それぞれの変数はオブジェクトIDからインスタンスをコントロールしている。

(左辺と右辺の変数自体は独立しているが、どちらも同じインスタンスを見ている。)

これ以上は想像でしかなくなるので止めますが、リファレンスやオブジェクトの代入と同じような動きを $GLOBALS はします。

というか、グローバルスコープならそのままグローバル変数($g_test)を使うべきだし、ローカルスコープなら global $g_test を使えばいいので、わざわざ $GLOBALS を直接編集する機会はない。

そして何より、PHP8.1ではこの不思議な動きはなくなっています。

同時にPHP8.1では $GLOBALS のリファレンス作成も禁止されシンタックスエラーになる。

修正されてるんだからもういいだろうと思うかもしれませんが、PHP8.1は2021年11月25日にリリースされたばかりで、この不可思議な挙動をするバージョンを使ってる人が多数です。

だから気をつけましょうということなんですが、普通に宣言されたグローバル変数を使い、globalキーワードを使ってる人には関係ありません。

結論なんですけど、$GLOBALSを直接参照するの止めませんか?

(絶対に使う機会はないとは言い切れないので例外はあっていいが。)

PHP公式ドキュメント

Variables - GLOBALS

オブジェクトと参照

前の投稿
PHP, globalキーワード付き変数は何なのか? $GLOBALS と何が違うのか?
PHP str_replace, 文字列の中から特定の文字列を削除する
次の投稿

コメントを残す