Da in letzter Zeit öfters Code von TS's gepostet wurde, der Fehlermeldungen ausgespuckt hat, zusammen mit der Frage, was falsch ist, habe ich dieses Tutorial erstellt. Kritik ist willkommen, aber bitte Konstruktiv.
Fehlerbehandlung in PHP
Um immer alle Fehler zu sehen, sollte man folgendes an den Anfang seiner PHP-Dateien setzen:
Hier werden evtl. viele NOTICE-Errors kommen. Daher sage ich zu denen auch noch was:
Ein E_NOTICE kommt meistens durch Unstimmigkeiten im Programmcode zustande. z.B.:
Hier wird mit einer nicht-definierten variable gerechnet. Die Zählt PHP normalerweise als Null,
aber wenn alle Errors an sind, erhält man eine Fehlermeldung.
Zitat
Notice: Undefined variable: a in foo.php on line 3
Hier könnte z.B. eine falsch geschriebene Variable der Grund für ein falsches Ergebnis sein, für das man evtl. seine Rechnung verantwortlich macht.
Der simpelste Fehler ist der Syntax-Error. Jedoch sind die Meldungen von PHP da nicht immer ganz eindeutig.
Das hier ergibt folgende Fehlermeldung:
Zitat
Parse error: syntax error, unexpected $end, expecting T_VARIABLE or T_DOLLAR_OPEN_CURLY_BRACES or T_CURLY_OPEN in /users/cptest/www/foo.php on line 3
PHP sagt uns hier, das Script hört unerwarteterweise auf. Warum? da gibt es doch ein ?>.
In PHP kann man beliebig viele Zeilenumbrüche in einen String packen. daher parst PHP den Code bis zum >, weil der String nicht geschlossen wurde. Aber beim > hört das Script auf und das ergibt die Fehlermeldung.
Hier parst PHP nur bis zum zweiten " und gibt den String aus, kein Fehler.
Eine komplexere Form des Syntax-Errors wäre z.B. das hier:
<?php
$foo="DeFbArxYZ";
if (strToLower(htmlspecialchars(mysql_real_escape_string(substr($_GET['bla'], 3, 4))) == strToLower(substr($foo, 3, 3))) {
echo "Ja";
} else {
echo "Nein";
}
?>
Und hier verliert man leicht die Übersicht. Da hilft natürlich erstmal ein Editor mit Syntaxhighlighting, der die Klammern hervorhebt.
Jedenfalls, PHP meckert hier:
Zitat
Parse error: syntax error, unexpected '{' in /users/cptest/www/foo.php on line 3
Da hilft es, zumindest gedanklich die Bedingung auseinanderzunehmen, denn einfach irgendwo eine Klammer setzen macht keinen Sinn.
<?php
$foo="DeFbArxYZ";
if
(
strToLower(
htmlspecialchars(
mysql_real_escape_string(
substr(
$_GET['bla'], 3, 4
)
)
)
==
strToLower(
substr(
$foo, 3, 3
)
)
) {
echo "Ja";
} else {
echo "Nein";
}
?>
Alles anzeigen
Und man erkennt ziemlich schnell, das strToLower im ersten teil der Bedingung nicht geschlossen ist.
Btw: Wenn das script mit einer Datenbank verbunden ist, ist die Ausgabe: Nein
Die Fehlermeldung des Typs "Warning" sind ähnlich zu behandeln, sie betreffen aber eher weniger den Code an sich. Ein typischer Fehler dieser Art ist dieser:
Zitat
Warning: Cannot modify header information - headers already sent by (output started at foo.php:3) in /users/cptest/www/foo.php on line 4
Das tritt immer dann auf, wenn man bereits eine Ausgabe gemacht hat, und dann die Funktion header() benutzt. Hier hilft es, das Script von vorne durchzugehen und die erste Ausgabe zu suchen.
Und weiter zum Tod jedes Scripts, zum Fatal-Error. Der kommt in den meisten Fällen bei Datenbankabfragen, daher nehme ich das im Beispiel.
<?php
$db=new mysqli("localhost", "user", "password", "datenbank");
$query=$db->query("SELECT foo, blub, defg, FROM abc WHERE d='bar', m='D'");
echo "<table><thead><td>foo</td><td>blub</td><td>defg</td></thead>";
while ($row=$query->fetch_array()) {
echo "<tr>";
foreach ($row as $v) {
echo "<td>".$row."</td>";
}
echo "</tr>";
}
echo "</table>";
$query->close();
$db->close();
// Ein meinem Fall existiert hier garkeine Datenbank, nur der Server ist online, d.h.,
// bereits der Verbindungsversuch schlaegt schon fehl. Wuerde die Verbindung jedoch
// klappen, wuerde das Script am falschen Query scheitern.
?>
Alles anzeigen
Das fuehrt zu einem Fatal-Error bei $query->fetch_array().
Zitat
Fatal error: Call to a member function fetch_array() on a non-object in /users/cptest/www/foo.php on line 5
Da gibts 2 moeglichkeiten, das Problem zu loesen.
1. Die mysql_* Funktionen benutzen und in diesem Fall nur ein Warning anstadt einem Error zu erhalten\
2. Pruefen, ob das Query durchgegangen ist und nur dann fetch_array() aufrufen.
Es ist wohl offensichtlich, dass hier 2. die bessere Idee ist.
<?php
$db=new mysqli("localhost", "user", "passwort", "datenbank");
if ($query=$db->query("SELECT foo, blub, defg, FROM abc WHERE d='bar', m='D'")) {
echo "<table><thead><td>foo</td><td>blub</td><td>defg</td></thead>";
while ($row=$query->fetch_array()) {
echo "<tr>";
foreach ($row as $v) {
echo "<td>".$row."</td>";
}
echo "</tr>";
}
echo "</table>";
$query->close();
}
$db->close();
?>
Alles anzeigen
Und damit kommen wir zum 3. Punkt, die Fehler bei SQL-Statements.
Nun kommt schonmal keine Fehlermeldung mehr, aber wissen, wo das Problem steckt, weis man immernoch nicht. Dazu steht die variable $error im mysqli-Object bzw. die mysql_error() funktion bereit.
Von den beiden erfahren wir naemlich immer, was gerade falsch lauft.
Wenn man also von einer If-Abfrage erfaehrt, dass der Query fehlgeschlagen ist, dann immer
EDIT:
Hier empfiehlt es sich jedoch, um SQL-Injector Angreiffern das Leben schwerer zu machen, diese Funktion zu benutzen:
function logError($message) {
if ($_SERVER['HOST_ADDR']=="127.0.0.1") {
// localhost, error ausgeben
echo "FEHLER: ".$message."<br>";
} else {
// online, ins logfile
file_put_contents(
"errorlog.txt",
file_get_contents("errorlog.txt").$message."\n"
);
}
}
Alles anzeigen
Im allgemeinen: Bitte ALLE Fehlermeldungen GENAU anschauen, mit dem Code abgleichen und dann verbesern