PHP 変数のスコープ
PHP のバリアブル(変数)にはスコープ (Scope) が存在します。これは、スクリプトのどの場所からその変数にアクセスしたり、値を変更したりできるかを決定するものです。すべてのバリアブルは特定のコンテキスト(文脈)の中に存在し、明示的に宣言しない限り、その有効範囲はそのコンテキスト内に厳格に制限されます。
1. ローカルスコープ (Local Scope)
関数の内部でデリクレア(宣言)されたバリアブルは、ローカルスコープを持ちます。これは、それらの変数がその特定の関数の内部からのみアクセス可能であることを意味します。関数が実行を完了すると、これらのローカル変数は破棄されます。
ローカルスコープを持つ変数は、それを宣言した関数の外部からアクセスすることはできません。グローバルスコープからローカル変数にアクセスしようとすると、「Undefined variable(未定義の変数)」エラーが発生します。
<?php
function greetUser() {
$message = "関数内部からの挨拶です!"; // $message はローカルスコープを保持
echo $message;
}
greetUser(); // 関数をコール。$message が生成され使用される
// 関数の外部から $message にアクセスしようとするとエラーになります
// echo $message; // この行は "Undefined variable: message" エラーを誘発します
?>上の例では、$message は greetUser() の内部で作成され、その関数が実行されている間だけ存在します。異なる関数であれば、同じ名前の変数を宣言しても衝突することはありません。それぞれのスコープが完全に隔離されているからです。
<?php
function calculateSum($a, $b) {
$result = $a + $b; // $result はローカルスコープを保持
return $result;
}
function displayGreeting($name) {
$greeting = "ようこそ、" . $name . "さん!"; // $greeting はローカルスコープを保持
echo $greeting . "\n";
}
$sum = calculateSum(5, 10);
echo "合計は:" . $sum . "\n";
displayGreeting("アリス");
// ここで $result や $greeting にアクセスしようとしても失敗します
// echo $result; // エラー
// echo $greeting; // エラー
?>calculateSum におけるパラメータ $a と $b もローカル変数であり、関数に渡される実際の値のプレースホルダーとして機能します。
2. グローバルスコープ (Global Scope)
いかなる関数の外部で宣言されたバリアブルは、グローバルスコープを持ちます。デフォルトでは、これらの変数はスクリプトのどこからでもアクセス可能ですが、唯一、関数内部から直接アクセスすることだけはできません。
関数内部からグローバル変数にアクセスするには、global キーワードを使用して明示的に宣言するか、$GLOBALS スーパーグローバル配列を介してアクセスする必要があります。
2.1 global キーワードの使用
global キーワードは PHP に対し、「関数内部のこの変数は新しいローカル変数を作成するのではなく、グローバルバージョンの変数を参照すべきである」と明確に指示します。
<?php
$appName = "私の PHP アプリ"; // $appName はグローバルスコープを保持
$version = "1.0"; // $version はグローバルスコープを保持
function displayAppInfo() {
global $appName; // この関数内の $appName がグローバルな $appName を参照するよう宣言
global $version; // この関数内の $version がグローバルな $version を参照するよう宣言
echo "アプリ名:" . $appName . "\n";
echo "バージョン:" . $version . "\n";
}
displayAppInfo(); // 出力:アプリ名:私の PHP アプリ,バージョン:1.0
function updateVersion() {
global $version;
$version = "1.1"; // グローバルな $version 変数を修正
echo "関数内部で更新されたバージョン:" . $version . "\n";
}
updateVersion(); // 出力:関数内部で更新されたバージョン:1.1
echo "現在のグローバルバージョン:" . $version . "\n"; // 出力:現在のグローバルバージョン:1.1 (外部の変数も変更されている)
?>global を使用することで、関数内部からグローバル変数に対するリード(読み取り)およびライト(書き込み)オペレーションが可能になります。
2.2 $GLOBALS スーパーグローバル配列の使用
PHP は $GLOBALS という特殊なスーパーグローバル配列を提供しています。この連想配列には、グローバルスコープで利用可能なすべての変数のリファレンスが含まれています。変数名がその配列のキー (Key) になります。
この方法は、コードの意図がより明確になり、潜在的なネーミングコンフリクト(名前の衝突)を避けられるため、多くの場合 global キーワードよりも好まれます。
<?php
$pageTitle = "製品リスト"; // グローバル変数
$itemsPerPage = 10; // グローバル変数
function generateHeader() {
// $GLOBALS 配列を使用してグローバル変数にアクセス
echo "<h1>" . $GLOBALS['pageTitle'] . "</h1>\n";
echo "<p>1ページあたり " . $GLOBALS['itemsPerPage'] . " 個のアイテムを表示します。</p>\n";
}
function updateItemsPerPage($newCount) {
// $GLOBALS 配列を使用してグローバル変数を修正
$GLOBALS['itemsPerPage'] = $newCount;
echo "1ページあたりのアイテム数が更新されました:" . $GLOBALS['itemsPerPage'] . "\n";
}
generateHeader();
// 出力:
// <h1>製品リスト</h1>
// <p>1ページあたり 10 個のアイテムを表示します。</p>
updateItemsPerPage(20); // グローバルな $itemsPerPage を修正
echo "更新後のグローバル itemsPerPage:" . $itemsPerPage . "\n"; // 出力:更新後のグローバル itemsPerPage:20
?>global $variable; と $GLOBALS['variable'] はどちらも関数内部からグローバル変数にアクセスするという目的を達成できます。$GLOBALS 配列はストリングキーを使用してダイナミックに変数を指定できるため、より柔軟です。
3. スタティックスコープ (Static Scope)
static(スタティック)キーワードは、関数内部のローカル変数に適用されます。関数が実行を終えると破棄される通常のローカル変数とは異なり、スタティック変数は同じ関数の複数回にわたるコール(呼び出し)の間で、最後に保持していた値を維持します。
スタティック変数はスクリプトの実行期間中、一度だけ初期化されます(つまり、関数が最初にコールされたときです)。
<?php
function trackVisits() {
static $counter = 0; // $counter はスタティック変数
$counter++;
echo "ページ訪問数:" . $counter . "\n";
}
trackVisits(); // 出力:ページ訪問数:1
trackVisits(); // 出力:ページ訪問数:2
trackVisits(); // 出力:ページ訪問数:3
// スタティック変数 $counter は関数の外部からはアクセスできません
// echo $counter; // これは "Undefined variable: counter" エラーになります
?>trackVisits() の例では、$counter は一度だけ 0 に初期化されます。その後のコールでは、以前の値(1、そして 2)を記憶しており、その値をベースにインクリメントされます。もし $counter が通常のローカル変数であれば、関数がコールされるたびに 0 にリセットされるため、出力は常に「ページ訪問数:1」となります。
スタティック変数は、グローバル変数に頼ることなく、また関数の内外で値をやり取りすることなく、関数内部で状態(ステータス)を維持したい場合に非常に適しています。
<?php
function generateUniqueId() {
static $lastId = 1000; // ベースとなる ID を初期化
$lastId++;
return "USER_" . $lastId;
}
echo generateUniqueId() . "\n"; // 出力:USER_1001
echo generateUniqueId() . "\n"; // 出力:USER_1002
echo generateUniqueId() . "\n"; // 出力:USER_1003
?>ここでは、generateUniqueId() がスタティック変数 $lastId を使用することで、生成される各 ID がユニークかつ連番であることを保証しています。