【PHP】Warning: Undefined variable の原因と解決方法|??・isset・スコープ

PHPで「Warning: Undefined variable $xxx」と表示されるのは、定義されていない変数を使おうとしたときです。よくあるのは変数名のタイプミスや、変数のスコープ(有効範囲)の勘違い、フォームから送られてこなかった値へのアクセスです。この記事では原因の見つけ方と、用途に応じた正しい対処方法を解説します。

この記事の結論:変数は使う前に初期化するのが基本です。「あるかもしれない/ないかもしれない」値にはnull合体演算子 ??(例: $x = $_POST["x"] ?? "";)が便利です。error_reporting で警告を隠すのは根本解決にならないので避けます。
スポンサーリンク

エラーの正体

未定義変数の参照は、PHP 8.0で「Notice」から「Warning」に格上げされました(PHP 7では Notice でした)。いずれも処理は止まりませんが、その変数は null(空)として扱われるため、表示や計算が意図どおりになりません。

未定義変数を使うと
<?php
echo $undefined_variable;
// Warning: Undefined variable $undefined_variable
// (変数は null 扱いになり、何も表示されない)

よくある原因

  • 変数名のタイプミス$userName$username を取り違えるなど
  • スコープ違い:関数の中で定義した変数を外で使おうとしている(後述)
  • 条件分岐の中だけで代入if が成立しなかったときに未定義になる
  • フォーム値の未送信$_POST["x"] が送られてこなかった(こちらは「Undefined array key」になることもあります)
まず変数名のスペルを疑いましょう。PHPの変数は大文字・小文字を区別します($Name$name は別物)。警告に出ている変数名と、代入している箇所の変数名が完全に一致しているかを確認してください。

対処方法

変数を初期化する(基本)

もっとも確実なのは、使う前に初期化しておくことです。ループで値をためる変数や、条件によって代入される変数は、先に初期値を入れておきます。

使う前に初期化
<?php
$total = 0;     // 数値なら0
$message = "";  // 文字列なら空文字
$items = [];    // 配列なら空配列

null合体演算子(??)でデフォルト値を使う(推奨)

「あるかもしれないし、ないかもしれない」値には ?? が最適です。左側が未定義または null なら右側の値を使います。警告も出ません

?? でデフォルト値
<?php
// $_POST["name"] が無ければ "" を使う(警告なし)
$name = $_POST["name"] ?? "";

// 変数にも使える
$value = $variable ?? "デフォルト値";

issetで存在を確認する

issetでチェック
<?php
if (isset($variable)) {
    echo $variable;
} else {
    echo "変数は定義されていません";
}
「空かどうか」まで判定したいときはemptyで変数や配列が空かどうか確認する方法、NULLの判定はNULL判定の方法が参考になります。

意外な落とし穴:変数のスコープ

関数の中で定義した変数は、その関数の外からは見えません(逆も同様)。これを忘れると「定義したはずなのに未定義」と言われます。値は引数で渡し、return で返すのが基本です。

スコープの誤り(NG)と正しい書き方(OK)
<?php
function calc() {
    $result = 100; // 関数の中だけのローカル変数
}
calc();
echo $result; // Warning: Undefined variable $result(外からは見えない)

// OK: 値は return で受け取る
function calc2() {
    return 100;
}
$result = calc2();
echo $result; // 100

error_reportingで隠すのは最終手段

開発中は error_reporting(E_ALL) ですべての警告を表示し、問題を見逃さないようにします。警告を消すために抑制するのは、バグの芽を隠すだけなので避けましょう。

開発環境ですべて表示する設定
<?php
ini_set('display_errors', '1');
error_reporting(E_ALL);
本番環境では画面にエラーを出さないのが原則です(display_errors = Off)。ただし警告自体はログに記録して、後から原因を直せるようにしておきます。警告を @error_reporting で握りつぶすのは、根本解決ではありません。

よくある質問(FAQ)

Q未定義変数は致命的エラーですか?
Aいいえ、Warning(警告)です(PHP 7まではNotice、PHP 8で警告に格上げ)。処理は止まりませんが、変数は null 扱いになるため結果が意図どおりになりません。早めに直しましょう。
Qisset と ?? はどう使い分けますか?
A存在を確認して分岐したいなら isset()未定義のときにデフォルト値を入れたいなら ?? が簡潔です。$x = $_POST["x"] ?? ""; のように書くと、存在チェックと既定値を1行で済ませられます。
Q定義したはずなのに未定義と言われます。
A変数名のタイプミススコープ違いが疑われます。PHPは大文字小文字を区別します。また関数内で定義した変数は外からは見えません。値は引数で渡し return で受け取ってください。
Qerror_reportingで警告を消してもいいですか?
Aおすすめしません。警告を消してもバグの原因は残ります。正しくは変数を初期化する・?? を使うなどで根本対処し、本番では画面表示をオフにしてログに記録します。

まとめ

「Undefined variable」への対処を整理します。

  • 未定義変数の参照は警告(PHP 8で格上げ)。変数は null 扱いになる
  • 原因の多くはタイプミス・スコープ違い・未送信のフォーム値
  • 基本は使う前に初期化する
  • あるかないか不定の値は ??(例: $_POST["x"] ?? ""
  • error_reporting隠すのは根本解決にならない

関連として、emptyで空かどうか確認する方法NULL判定の方法Array to string conversion エラーの対処方法もあわせて読むと、PHPのエラー対処に強くなれます。