「Notice: Undefined index」「Notice: Undefined variable」の解決と解説

僕が最初にPHPを使いだして、初めてぶつかったエラーでした。
文字通りなのですが、「Notice: Undefined index」は定義されていない配列の要素、「Notice: Undefined variable」は定義されていない変数を使用した場合に発生します。echoしたり関数の引数として使った場合ですね。
なお、単純に変数名やindex名を誤って記述した時にも出ます。

対処法

Noticeエラーは、「望ましくない」コードに対してでるものなので、プログラムは動作します。そのため、エラーを表示しないという対応も可能ですが、本来はエラーの発生しないコードを書くことが望ましいです。

「Notice: Undefined variable」は変数を最初に初期化して解決

$var1 = $var2; //var1var2も初出。Undefined variableが出る

$var2 = NULL;
$var1 = $var2; //Undefined variableは出ない

初出の変数はNULLを代入*1し、初期化してから使用するようにします。未定義の変数"に"代入する(未定義の変数が左側)ことは可能ですが、未定義の変数"を"代入する(未定義の変数が右側)とエラーが出るわけです。

「Notice: Undefined index」はindexの有無を確認する処理を入れて解決

最初に該当のindexが存在するかを確認し、存在しない場合の処理を記述します。

if ( $_POST['name'] == "" ){

  echo '名前を入力してください';

} //リクエストにnameフィールドが含まれていないとNotice undefined indexが出る



if(isset($_POST['name'])) {

  if ( $_POST['name'] == "" ){

  echo '名前を入力してください';

  }

} //Notice undefined indexは出ない


又は

if ( !isset($_POST['name']) || $_POST['name'] == "" ){

  echo '名前を入力してください';

} //Notice undefined indexは出ない


issetは該当の変数に値がセットされていればtrue、いなければfalseを返します。上の例では$_POST['name']がセットされている場合のみ規定の処理を行い、そうでなければ何もしません。
下の例では、$_POST['name']がセットされていないか空の文字列の時に「名前を入力してください」と出力します。!はNOTの意味です。||はorの意味で、片方がtrueだった時点で処理が実行されます。例文では!isset($_POST['name'])を前に置くことで、エラーが出なくなっています。

もちろん、こんなシンプルな例なら

$words = array('a' => 'apple', 'b' => 'book');

echo $words['c']; //Notice undefined indexが出る

変数を初期化したように、該当のindexを追加するだけで簡単に解決します。
$words['c'] = "";

@をつけてNoticeエラーを非表示にする

処理や変数の前に@を付けることでNotice、Warningを該当部分のみ非表示にできます。

  echo @$undefined;

スクリプト内でNoticeエラーを非表示にする

そのスクリプト内でのエラー表示をerror_reporting関数で制御できます。

error_reporting(E_ALL ^ E_NOTICE);

php.iniの設定でNoticeエラーを非表示にする

php.ini内のerror_reportingを変更することで、まとめて制御できます。僕の手元では270行目あたり。

error_reporting = E_ALL & ~E_NOTICE

E_ALLは全てのエラー、~は除くE_NOTICEはNoticeエラーで、Noticeエラーを除く全てのエラーを表示という意味になります。php.iniを書き換えたらwebサーバーを再起動して設定を反映するのを忘れないようにします。

GETやPOSTで発生する大量の「Notice: Undefined index」

GETやPOSTをした時にこのエラーに出会うというケースは多いのではないでしょうか。
外部からの変数:$_GETと$_POST

//submit.php

<form action="confirm.php" method="POST">

   <label for="name">名前</label><input type="text" name="name">

   <input type="submit" value="確認">

</form>



//confirm.php

<?php

echo '名前:'.$_POST['name'];

?>

上記の例では、submit.phpのフォームに名前を入力して確認ボタンを押すと、POSTメソッドで入力データが送られ、それをconfirm.phpで取得後、出力して確認しています。
ここで仮にsubmit.phpの確認ボタンを経由せず、URL直打ちでconfirm.phpを見るとUndefined indexが出ます。
POSTメソッドを実行した時には、$_POST['formのname属性']という連想配列を定義しているようなものなので、そのPOSTメソッドが実行されなければ、定義していないindexを出力しようとしている状態になるわけです。

*1:初期化時に何を代入するかという議論もあるようですがここでは触れません