Notice: Undefined index
Die „Fehlermeldungen“, die keine Fehler sind

Was ist das denn für eine Fehlermeldung?

Oft wird von Anfängern angemerkt, dass es beim Ausführen des Scripts eine Fehlermeldung gibt, das Script aber trotzdem funktioniert. Immer und immer wieder bekommt man sie beim PHP-lernen: Sogenannte „notices“. Doch was sind das eigentlich für Meldungen?
Übersetzt man den Begriff aus dem englischen, so bemerkt man, dass es eigentlich kein Fehler (engl. Error) ist, sondern lediglich eine Notiz ? der PHP-Interpreter merkt hier also lediglich etwas an, was den Programmablauf aber nicht beeinflussen muss. Dennoch ist es für Anfänger sehr verwirrend, wenn auf einmal etwas auftaucht, was wie eine Fehlermeldung aussieht ? aber trotzdem alles funktioniert. Deshalb soll hier kurz erklärt werden, warum diese Notizen entstehen und wie man sie vermeiden kann.

Woher die Notizen kommen

Als Beispiel-Code soll uns hier der Code des Reservierungsbeispiels vom DVD-Kurs dienen:

<?php
if ($_GET['nachname'] == "" or $_GET['anzahl'] == "" ) 
{
    echo '<form action="reservierung.php" method="get">';
    echo '<p>Nachname:<br />';
    echo '<input type="text" name="nachname" size="20" value="" />';
    echo '<p>Anzahl gewünschter Reservierungen<br />';
    echo '<input type="text" name="anzahl" value="" size="4" />';
    echo '<p><input type="submit" value="absenden" />';
    echo '</form>';
}
?>

Führt man diesen Code aus, erhält man bei Standardeinstellungen folgende Meldung:
Notice: Undefined index: nachname in C:\xampp\htdocs\reservierung.php on line 2
Der Code aber funktioniert und nach dem Absenden des Formulars ist die Meldung weg, warum also kommt sie zustande?
Der Fehler liegt nach Aussage der Meldung in Zeile 2 ? schauen wir uns also diese Zeile einmal näher an:

if ($_GET['nachname'] == "" or  $_GET['anzahl'] == "" ) 

Hier wird geprüft, ob einer der GET-Werte nachname oder anzahl leer ist, um in diesem Fall das Formular noch einmal anzuzeigen.
Aber halt.. welcher GET-Wert denn eigentlich? Wenn man den Code ganz korrekt von oben nach unten abarbeitet (was der PHP-Interpreter auch tut), fällt auf, dass bis jetzt kein einziger GET-Wert gesetzt wurde. Der Wert für $_GET['nachname'] ist also schlichtweg nicht vorhanden. Und genau das sagt auch die Meldung aus: Undefined index bedeutet nichts weiter, als dass der GET-Wert mit diesem index nicht definiert ist ? somit kann auch nicht geprüft werden, ob dieser Wert leer ist.
Die Notice entsteht also deshalb, weil ein nicht vorhandener Wert überprüft wird.

Warum funktioniert das Script trotzdem?

Dann stellt sich also die Frage: Warum funktioniert das Script? Ganz einfach deshalb, weil nicht vorhandene Werte eben auch als leere Werte gesehen werden. Somit ist die if-Bedingung erfüllt und das Script wird in der Schleife fortgesetzt. Schickt man das Formular ab, ist die Notice weg ? denn nun sind die GET-Werte gesetzt. Auch wenn das Formular leer abgeschickt wird gibt es keine Notice mehr ? denn der GET-Wert ist gesetzt (nur eben leer) ? das Formular wird angezeigt, nur gibt es keine Notice mehr.

Was man gegen die Notizen tun kann

Auch wenn sie eigentlich nicht weiter schlimm sind, so stören sie den einen oder anderen Programmierer doch, diese nervigen Notizen.
Vorweg kann gesagt werden: Stellt man ein Projekt ins Netz und testet nicht mehr nur lokal, werden solche Notizen in der Regel generell abgestellt. Dafür gibt es verschiedene Möglichkeiten, auf die hier aber nicht weiter eingegangen werden soll, da es zum Lernen nicht unbedingt gut ist, alle Fehlermeldungen abzustellen.
Es gibt allerdings auch eine andere Variante, die speziell diesen Notices entgegenwirkt:
Die PHP-Funktion isset(). Wie der Name schon sagt, überprüft diese Funktion, ob z.B. unser GET-Wert gesetzt ist. Damit wollen wir nun unser Script erweitern, sodass das Script auch in die if-Bedingung springt, wenn $_GET['nachname'] oder? $_GET['anzahl'] nicht gesetzt sind. Da isset() überprüft, ob eine Variable gesetzt ist, wir aber das Gegenteil brauchen, stellen wir dem isset ein Ausrufezeichen (!) voran, um das Gegenteil auszudrücken. In die Klammer der Funktion kommt die Variable, die wir überprüfen wollen:

!isset($_GET['nachname'])
!isset($_GET['anzahl'])

Das müssen wir nun noch in unser Script einbauen. Dabei werden diese beiden Möglichkeiten den schon vorhandenen Möglichkeiten in der if-Bedingung mit OR vorangestellt. Würden wir sie hintenan stellen, bekämen wir wieder eine Notiz, da die Möglichkeiten der Reihe nach abgearbeitet werden und nach der ersten zutreffenden der Code in der if-Bedingung ausgeführt wird. Durch Voranstellen wird, falls einer der beiden Werte nicht gesetzt ist, direkt der Code in der Bedingung ausgeführt, ohne die anderen Möglichkeiten (die ja die Notice hervorrufen) zu überprüfen.
In unseren Code eingesetzt sieht das dann so aus:

<?php
if ( !isset($_GET['nachname']) 
     or !isset($_GET['anzahl']) 
     or $_GET['nachname'] == "" 
     or $_GET['anzahl'] == "" 
   ) 
{
    echo '<form action="notice.php" method="get">';
    echo '<p>Nachname:<br />';
    echo '<input type="text" name="nachname" size="20" value="" />';
    echo '<p>Anzahl gewünschter Reservierungen<br />';
    echo '<input type="text" name="anzahl" value="" size="4" />';
    echo '<p><input type="submit" value="absenden" />';
    echo '</form>';
}
?>

Testen und ? die Notice ist weg. Das Programm funktioniert nun genauso wie vorher ? mit dem Unterschied, dass nun keine Notice mehr kommt, da diese durch die Überprüfung durch isset() abgefangen wird.

Was bewirkt ein @ vor der Variable?

Viele Neulinge in PHP, die zum ersten Mal eine solche Notiz bekommen, versuchen diese mit aller Macht weg zu bekommen, obwohl eigentlich nicht nötig. In der Tat bekommt man auch keine Notizen mehr, wenn man ein @ vor die entsprechende Variable stellt:

<?php
if ( @$_GET['nachname'] == "" or @$_GET['anzahl'] == "" ) 
{
    // restlicher Code
}
?>

Aber: Dadurch werden auch alle anderen Fehlermeldungen, die die Variable eventuell verursachen könnte, unterdrückt! Somit ist diese Methode für Anfänger nur bedingt geeignet ? wen die Notizen stören, sollte lieber die oben beschriebene Methode verwenden, um bei Fehlern Fehlermeldungen zu erhalten. Mit dem @ arbeitet man also „quick and dirty“. Man sollte es also nicht tun!

Warum wird die Fehlermeldung im Kurs nicht erwähnt?

Da der PHP-kurs.com ständig erweitert wird, sind nicht immer alle Inhalte bis ins Detail auf dem aktuellen Stand. Dadurch, dass es in einer früheren PHP-Version diese Notizen noch nicht gab, werden sie im Kurs nicht erwähnt.
Weiterhin kommt es auch immer auf die Einstellung des Servers an:
Beim lokalen XAMPP-Server werden standardmäßig alle Fehler angezeigt, bei den meisten online-Servern werden keine Fehler angezeigt (bzw. für den Fehler spezifische Fehlermeldungen für User, ohne Zeilennummer o.Ä. zu nennen), um besseren User-Comfort zu erreichen und potenziellen Angreifern weniger Angriffsfläche zu bieten.

Notizen abschalten

Natürlich lassen sich die Notizen auch unterdrücken (was aber zum Lernen nicht sinnvoll ist), dafür wird die PHP-Funktion error_reporting() verwendet:

error_reporting(0);
error_reporting(E_ALL); 

error_reporting mit dem Wert 0 schaltet alle Fehlermeldungen komplett aus, während E_ALL jede Meldung anschaltet. Man kann jedoch auch spezifisch die verschiedenen Fehlertypen an bzw. ausschalten. Um nur die Notizen auszuschalten, verwendet man E_ALL und schließt durch ^ E_NOTICE aus:

error_reporting(E_ALL ^  E_NOTICE); 

Somit gibt es keine Notizen mehr, alle anderen Fehler werden aber angezeigt.