PHP入門 変数の有効範囲(スコープ)
ユーザー定義関数の有効範囲(スコープ)について解説しています。
スコープ
スコープとは、スクリプトの中での変数の有効範囲のことです。PHPのスコープは、スクリプト全体から参照できるグローバルスコープと、定義された関数の中でのみ参照できるローカルスコープとに分類できます。
グローバル変数とローカル変数
グローバルスコープを持つ変数をグローバル変数、ローカルスコープを持つ変数のことをローカル変数と言います。変数がグローバル変数/ローカル変数のいずれかであるかは、変数の定義している場所によります。
<?php
$x = 10;
function checkScope(): int{
return ++$x;
}
print checkScope(); //結果:1
print $x; //結果:10
グローバル変数とローカル変数、スコープの異なる変数は、名前が同一であっても違う変数とみなされる。
関数内でグローバル変数を利用する(global命令)
例外的に関数ブロックの中からグローバル変数を操作したい場合、global命令を利用します。ローカル変数を強制的にグローバル変数に割り当てることができます。
<?php
$x = 10;
function checkScope(): int{
global $x; //➊
return ++$x;
}
print checkScope(); //結果:11
print $x; //結果:11
➊によって、関数内の$xがグローバル変数とみなされます。
静的変数(static命令)
関数の終了後もローカル変数を保持していくには、静的変数を利用します。静的変数は、static命令で定義できます。静的変数は、関数の初回呼び出し時にのみ初期化され、その後、関数の処理が終了しても維持されます。「静的変数はあくまでローカル変数である」ということであり、有効なのは関数ブロックの中だけです。
<?php
$x = 10;
function checkStatic(): int{
static $x = 0;
return ++$x;
}
print checkScope(); //結果:1
print checkScope(); //結果:2
print $x; //結果:空(null)
インクルードファイルのスコープ
require_once命令などによって読み込まれたインクルードファイルのスコープは、読み込み元のスコープによって変動します。つまり、関数の外でファイルを読み込んだ場合、インクルードファイルのスコープはグローバルスコープになりますし、関数の中から読み込んだファイルはローカルスコープとなります。
例:インクルードファイルを、それぞれ関数の外、中から読み込む
scope_included.php
<?php
$scope = 'アクセスできました。';
scope_include_global.php
<?php
require_once 'scope_included.php';
print $scope; //結果:アクセスできました。
scope_include_local.php
インクルードファイルファイルがcheckScope関数の中から呼び出されるので、変数$scopeはローカルスコープとなります。結果、checkScope関数経由であれば変数$scopeにアクセスできます。
<?php
function checkScope(): string{
require_once 'scope_included.php';
return $scope;
}
print checkScope(); //結果:アクセスできました。
print $scope; //結果:カラ(表示されない)
unset関数の挙動
unset関数を利用することで変数を破棄できます。しかし、globalキーワードで定義された変数や、静的変数(static変数)を破棄する場合には、注意する点もあります。
globalキーワード
<?php
$x = 10;
function checkScope(): int{
global $x;
unset($x);
return ++$x;
}
print checkScope(); //結果:1
print $x; //結果:10
あくまで破棄されるのは「グローバル変数のようにふるまうローカル変数」だけです。関数外部のグローバル変数には影響しません。
関数の中でグローバル変数を破棄したい場合は
unset($GLOBALS['x']);
のように。$Globalsを介する必要があります。$GLOBALSは、すべてのグローバル変数を管理する特殊な連想配列です。
staticキーワード
静的変数を破棄したい場合は、その関数での以降の処理でのみ変数を破棄します。
<?php
function checkStatic():void{
static $x =0; //➊
$x++; //➊
print "unset前:{$x}"; //➊
unset($x); //➋
$x = 13; //➌
print "unset後:{$x}<br />" //➌
}
checkStatic(); //結果:unset前:1 unset後:13
checkStatic(); //結果:unset前:2 unset後:13
この例の場合、➊の段階では静的変数は有効です。そして、➋で$xを破棄していますが、この時点でも、静的変数を解除して一時的に$xをローカル変数にしているというだけで、静的変数そのものは破棄されていません。そのため、➌で$xに異なる値をセットしても、静的変数$xには影響が及ばないというわけです。