関数を使う上でスコープの理解は必須となります。
PHPのグローバルスコープ、ローカルスコープ、スーパーグローバルについて紹介します。
PHPのスコープを一言でまとめると、「関数の外で作った変数は関数の中からは見えず、関数の中で作った変数は外からも他の関数からも見えない」です。関数の中でグローバル変数を使いたいときはglobalキーワードか$GLOBALS配列を使います。$_SERVERや$_POSTなどのスーパーグローバルだけは、どこからでもそのまま使えます。if文やfor文の{}は新しいスコープを作りません。
スコープとは
スコープとは、変数が参照可能な範囲のことをいいます。
次の3つのスコープがあります。
- グローバルスコープ
- ローカルスコープ
- スーパーグローバル
以下に例を出しながら説明します。
<?php
// グローバルスコープ
$globalVal = 10;
function func() {
// ローカルスコープ
$localVal = 20;
}
function func2() {
// ローカルスコープ
print_r($localVal); // func()の$localValは見えないので Undefined variable
print_r($globalVal); // グローバルの$globalValもこのままでは見えない
}
func2();
上のようにファイルに記述されていて、{}に囲まれていない変数は、グローバルスコープの変数となります。
関数の中で宣言されている変数は、ローカルスコープとなります。
ローカルスコープの注意点
大事な点としては、ローカルスコープで宣言された変数は、ローカルスコープ内でのみ有効となります。
つまり、func()の中の変数は、func()のローカルスコープ外であるfunc2()の中では、使えないということです。
「Undefined variable」という警告(PHP 8以降はWarning、PHP 7まではNotice)が出ている場合、スコープの外にある変数を参照していないかを確認します。変数が定義済みかどうかを先に調べたいときは、isset()とempty()の使い方が役立ちます。
ローカルスコープのメリット
ローカルスコープのメリットは、使える範囲が制限されることで、思わぬバグの混入を防げる点です。
グローバルスコープで変数を宣言しすぎると、意図せず変数がかぶってしまって思わぬバグを生むことがあります。
ローカルスコープを使えば、使いたいところでのみ変数を有効にできます。
また、関数ごとに同じ変数名であっても使えます。
関数内でグローバルスコープの変数を使いたいとき
<?php
// グローバルスコープ
$globalVal = 10;
function func3() {
// ローカルスコープ
$localVal = 20;
global $globalVal;
echo $globalVal;
}
func3();
上のように、グローバルスコープで宣言された変数を関数内のローカルスコープで使うときは、globalキーワードを使います。
globalと記述して、その変数名を書きます。
そうすることで、ローカルスコープ内でも使えるようになります。
同じことは$GLOBALS['globalVal']と書いても実現できます。ただし、関数の中からグローバル変数を書き換える設計は追いにくいバグの原因になりやすいため、基本は引数で渡して戻り値で返します。どこからでも同じ値を参照したいだけなら、スコープの影響を受けない定数にする方法もあります(定数の使い方とconstとdefineの違い)。
スーパーグローバルについて
<?php
function func4() {
// ローカルスコープ
var_dump($_SERVER);
}
func4();
スーパーグローバルの変数は、globalキーワードが必要のない変数のことを言います。
$_SERVERのほか、$_GET、$_POST、$_SESSION、$_COOKIE、$GLOBALSなどがあります。
スーパーグローバルの場合は、関数内で直接使えます。
if文ではローカルスコープは形成されない
プログラミング言語の中には{}などでローカルスコープが形成されるものもありますが、PHPでは、if文ではローカルスコープは形成されません。
<?php
if (true) {
$inIf = 'ok';
}
echo $inIf; // ok(if文の外からも参照できる)
for文やwhile文も同じで、ブロックの中で作った変数はブロックを抜けたあとも使えます。JavaScriptのletやconstに慣れていると混乱しやすい点です。