Unterabschnitte


Fehlersuche

Auch wenn man sehr gut programmieren kann und sowohl PHP als auch SQL ,,im Schlaf`` beherrscht, kommt es vor, daß es ,,nicht so tut`` wie man will. In solchen Fällen ist es praktisch, wenn man weiß, wie man auf Fehlersuche gehen kann.

Als erstes sollte man sich natürlich überlegen, in welcher Reihenfolge das Programm was wie tun sollte und dann überprüfen, bis zu welchem Punkt es funktioniert. Um das festzustellen, gibt es verschiedene Methoden; am sinnvollsten ist es i.d.R., zu überprüfen, ob die Variablen die Werte haben, die sie haben sollten. Dazu kann man sie z.B. einfach mit echo ausgeben. Bei Arrays kann die Funktion var_dump($var) sehr praktisch sein. var_dump gibt nämlich das gesamte Array mit Index und Werten aus. Da es aber in HTML vorkommen kann, daß Text lediglich im Quelltext der Seite sichtbar wird (innerhalb von Tabellenkonstrukten zum Beispiel), ist es sinnvoll, einfach noch einen festen String mit auszugeben; auf diese Weise weiß man nachher auch noch, welche Variable es genau war. Als Beispiel haben wir die Variablen `VAR1` und `VAR2`:

echo $VAR1.'AAA';
echo $VAR2.'BBB';

Für reine Testzwecke hat es sich auch als hilfreich erwiesen, um die Testausgabe der Variablen herum einen HTML-PRE-Block zu setzen. Das bewirkt dann mit Sicherheit eine Darstellung der Ausgabe auch auf dem Bildschirm:

echo "<pre>";
echo $VAR1." ".$VAR2;
echo "</pre>";

Die dritte Möglichkeit schließlich findet dann Anwendung, wenn man mehrere Variablen, z.B. von POST/GET-Daten oder Servervariablen, im Zusammenhang sehen will und vielleicht die Namen einiger dieser Variablen gar nicht kennt. In diesem Fall kann man auf die PHP-interne Funktion phpinfo() zurückgreifen, die eine komplette HTML-Seite voll mit datenüberfüllten Tabellen ausgibt. Hierüber lassen sich dem System auch ,,intime Details`` über die Serverkonfiguration, den User-Agent (Browser) uvm. entlocken.

Bei IF-Abfragen z.B. kann es auch passieren, daß Anweisungen gar nicht erst ausgeführt werden. Um das zu überprüfen, setzt man einfach ein `echo` in die Abfrage hinein. Zum Beispiel:

$i=1;
echo $i.'CCC';
if (i==1){
  echo 'DDD';
  ....
}
Bei dieser Abfrage würde man auf den ersten Blick davon ausgehen, daß `1CCCDDD` ausgegeben wird, da $i, durch das erste `echo` bewiesen, den Wert 1 hat. Da man nun aber weiß, daß etwas mit der IF-Abfrage nicht stimmt, kann man auch einen zweiten Blick riskieren und sieht dann, daß beim i das $ fehlt.

Ein anderes Problem tritt häufig auch im Zusammenhang mit Strings auf - warum wird wohl bei folgendem String nicht das gewünschte ausgegeben:

$text = 'Alternativtext';
echo "<img src=\"bild.gif\" width=\"10\" height=\"10\"";
echo " alt=\".$text.\">";
Oder warum bekommen wir hier eine Fehlermeldung:
$text = 'Alternativtext';
echo "<img src=\"bild.gif\" width=\"10\" height="10"";
echo " alt=\"".$text."\">";
Ganz einfach: Das Escapen stimmt nicht. Im oberen Beispiel sind hinter `alt=` zwar die doppelten Anführungsstriche escaped, aber da direkt im Anschluß daran mit Hilfe des Stringoperators Strings verbunden werden, müßten an dieser Stelle noch einmal doppelte Anführungsstriche stehen, genauso wie bei der zweiten Stringverbindung. Im unteren Beispiel wurden zwar die Strings korrekt beendet und wieder angefangen, dafür wurden die Anführungszeichen um die `10` nicht escaped. Komplett richtig muß es so aussehen:
$text = 'Alternativtext';
echo"<img src=\"bild.gif\" width=\"10\" height=\"10\"";
echo " alt=\"".$text."\">";
Solcherlei Vergeßlichkeiten sind nicht selten Grund genug für eine langwierige Fehlersuche. Man kann dies aber von vorne herein vermeiden, indem man gleich gut nachdenkt und dabei alle doppelten Anführungszeichen, die wirklich ausgegeben werden sollen, escaped. :-)

Häufig funktioniert zwar der komplette PHP-Teil, die SQL-Anweisungen jedoch nicht. In diesen Fällen gebe ich selbst einfach den Abfrage-String mit ` echo` aus.[*] Dann sieht man nämlich schon häufig den Fehler - ein häufiger ist übrigens, daß ein Feld einen String erwartet (z.B. die SQL-Typen TEXT und VARCHAR), in der Abfrage jedoch die für Strings charakteristischen Hochkommata vergessen wurden. Wenn man ihn jedoch nicht findet, benutzt man einfach den String und gibt ihn direkt am SQL-Prompt[*] ein. Wenn es dann immer noch nicht funktioniert, kürzt man die Abfrage solange, bis sie funktioniert. Die andere Richtung funktioniert natürlich auch, d.h. man konstruiert sich die Abfrage Stück für Stück zusammen und probiert, wie lange sie noch funktioniert und hat dann hoffentlich den Fehler.

Damit wären wir auch schon beim nächsten Punkt der Fehlersuche angelangt: Wenn etwas nicht laufen will, ersetzt man die Variablen durch Konstanten und probiert. Auf diese Weise ist nämlich eine Fehlerquelle (falsche Werte bei den Variablen) ausgeschlossen. Bei großen PHP-Dateien ist es teilweise sinnvoll, den nicht funktionierenden Teil in eine Datei zu kopieren, denn nicht selten werden Anweisungen durch andere beeinflußt, die eigentlich gar nichts miteinander zu tun haben (sollten).

Wenn es immer noch nicht funktioniert, hilft es vielleicht, wenn ein Freund, der auch etwas programmieren kann (das muß nicht einmal PHP sein) das Ganze mal begutachtet - denn vier Augen sehen mehr als zwei.

Jeder hat natürlich seine eigene Art, eine Fehlersuche anzugehen. Ich selbst habe hier nur kurz zeigen wollen, wie ich es mache (und damit bisher immer zum Ziel gekommen bin!). Wahrscheinlich habe ich wieder die Hälfte vergessen, aber du kannst mich natürlich auch auf bessere Methoden aufmerksam machen (gilt übrigens für die gesamte Anleitung)!


Übungen

Man lernt die Fehlersuche nirgendwo so gut wie beim Selbermachen. Ich habe hier mal versucht, ein paar ``typische`` Fehler zu sammeln. Für alle Übungen gelten folgende Fragen:

Die Lösungen befinden sich im Anhang B.7.


Ein komisches IF

Teil 1

<?php
$i = 0;
if ($i = 1){
  echo "Die Variable $i hat den Wert 1";
}
else {
  echo "Die Variable hat nicht den Wert 1";
}

Teil 2

$i = 0;
if ($i = 0){
  echo "Die Variable $i hat den Wert 0";
}
else {
  echo "Die Variable hat nicht den Wert 0";
}
?>

Fehler in einer leeren Zeile?

Die Zeilennummern sind hier nur der Übersichtlichkeit halber eingefügt worden. Sie stehen natürlich nicht in der PHP-Datei.
<?php
for ($i=1; $i<=5; $i++){
echo "$i<br>\n";
echo "Das waren die Zahlen 1-5";
?>

Wieso fehlt ein `;` wo eins ist?

Wie im vorigen Beispiel sind die Zeilennummern wieder nur der Übersichtlichkeit halber eingefügt worden.
<?php
for ($i=1; $i<=5; $i++){
  echo "$i<br>\n;
}
echo "Das waren die Zahlen 1-5";
?>

Christoph Reeg