Um kryptischen PHP-Fehlermeldungen zu umgehen, kann man die Error-Handling-API von PHP zum Entwickeln eigener Error-Handler nutzen. Damit sind Scriptfehler einfacher zu finden und zu verwalten.
Wer schon länger mit PHP arbeitet, wird wahrscheinlich wissen, was passiert, wenn es bei einem PHP-Script einen Fehler gibt. Üblicherweise erzeugt der PHP-Parser eine Fehlermeldung auf dem Bildschirm, die etwa so aussieht: Fatal error: Call to undefined function on line 19. Dann stoppt der PHP-Parser die Codeausführung.
Dieses Problem lässt sich aber lösen. PHP bringt von Haus aus eine Reihe von Tools mit, mit deren Hilfe der Entwickler Scriptfehler aufspüren und sie an ihren eigenen, benutzerdefinierten Error-Handler umleiten kann. Diesen Handler kann man dann so programmieren, dass er eine informativere Fehlermeldung anzeigt, den Fehler in einer Logdatei oder Datenbank protokolliert und/oder Gegenmaßnahmen einleitet.
In diesem Artikel soll gezeigt werden, wie man die Error-Handling-API von PHP zum Entwickeln eigener Error-Handler nutzen kann, so dass Scriptfehler auf einfache und benutzerfreundliche Weise angezeigt und verwaltet werden können. Zuerst die Grundlagen. PHP kennt drei grundlegende Fehlertypen, die nach ihrem Schweregrad abgestuft sind: Benachrichtigungen (notices), Warnungen (warnings) und Fehler (errors beziehungsweise fatals). Normalerweise führen Warnungen und Benachrichtigungen nicht zum Abbruch eines Scripts, fatal errors hingegen weisen auf schwerwiegende Fehler hin (zum Beispiel den Aufruf einer nicht existierenden Funktion oder eine Referenz auf ein nicht vorhandenes Objekt), die zum sofortigen Abbruch des Scripts führen. Solche Fehler können schon beim Starten des Scripts, beim Parsen, Kompilieren, zur Laufzeit oder nach Bedarf vom Script erzeugt werden.
Schlüsselbegriffe wie E_NOTICE, E_ERROR und so weiter beziehen sich auf die unterschiedlichen Fehlertypen und -stufen. Eine vollständige Liste samt der zugehörigen Bitmasken findet sich im PHP-Manual[1].
Für jedes Script wird die Fehleranzeige mithilfe der Funktion error_reporting() kontrolliert. Diese Funktion erwartet eine Liste von Parametern, die den einzelnen Fehlerstufen entsprechen, die berichtet werden sollen. Wie dies in der Praxis aussieht, zeigt das folgende Script (Listing A), welches nur Warnungen und Fehler meldet:
Listing A
Man vergleiche dies mit dem Script in Listing B, wo sämtliche Fehler - selbst die schwerwiegenden - verborgen werden:
Listing B
Oder mit diesem Script (Listing C), wo alle Fehler angezeigt werden, auch einfache Benachrichtigungen:
Listing C
Wie die obigen drei kurzen Beispiele illustrieren, ist die Funktion error_reporting() wichtig für die Kontrolle, welche Fehlermeldungen der Benutzer überhaupt zu Gesicht bekommt. Das Schlüsselwort lautet hier "zu Gesicht bekommt", denn nur weil ein Fehler nicht angezeigt wird, bedeutet dies nicht, dass er nicht aufgetreten ist. Das heißt, auch wenn überhaupt keine Fehler berichtet werden, wird ein schwerwiegender Fehler (zum Beispiel ein falscher Funktionsaufruf) die Ausführung des Scripts abbrechen, nur dass der Benutzer keine Fehlermeldung zu sehen bekommt, die ihn darüber informiert.
Das folgende Beispiel (Listing D) illustriert dies:
Listing D
Hier tritt ein schwerwiegender Fehler zwischen den beiden Aufrufen von echo() auf, wodurch die Ausführung des Scripts an der entsprechenden Stelle abgebrochen wird. Aber weil alle Fehlermeldungen deaktiviert wurden, erfährt der Benutzer hiervon nichts und nimmt womöglich an, dass das Script erfolgreich ausgeführt wurde. Offensichtliches Fazit: Das Deaktivieren von Fehlermeldungen ist eine höchst gefährliche Sache, weil es zu irrigen Annahmen darüber führen kann, ob ein Prozess erfolgreich abgeschlossen wurde oder nicht.
Tipp: Wenn man error_reporting() ohne Parameter aufruft, wird der aktuelle Status des Fehler-Reportings zurückgegeben. Nun da klar ist, dass das vollständige Abstellen aller Fehlermeldungen eine schlechte Idee ist, wird man sich wahrscheinlich fragen, welche anderen Möglichkeiten es gibt. Eine der elegantesten Lösungen des Problems besteht darin, PHPs standardmäßiges Error-Handling-System durch ein eigenes zu ersetzen. Ein solcher eigener Error-Handler kann so eingerichtet werden, dass er Fehler so behandelt, wie man es gern möchte, von der Anzeige der Meldungen bis zum Format, in dem die Fehler protokolliert und verfolgt werden.
Die entsprechende PHP-Funktion hierfür heißt set_error_handler(). Sie erwartet den Namen einer benutzerdefinierten Funktion, an welche die Fehler übergeben werden. Wenn ein Fehler auftritt, wird diese Funktion automatisch mit vier Parametern aufgerufen: dem Fehlercode und der entsprechenden Nachricht, dem Namen des Scripts, das den Fehler erzeugt hat, sowie der Zeilenzahl der Anweisung, die den Fehler ausgelöst hat. Die Funktion ist dann verantwortlich dafür, wie sie mit dem Fehler umgeht.
Hier ein einfaches Beispiel (Listing E):
Listing E
Wenn man dieses Script ausführt, sollte man so etwas zu sehen bekommen:
Hier wurde der Standard-Error-Handler von PHP durch den Code in der benutzerdefinierten Funktion myHandler() ersetzt. Wenn die Variable $undefVar aufgerufen wird, wird während der Laufzeit eine PHP-Benachrichtigung über undefinierte Variablen erzeugt und an die Funktion myHandler() weitergereicht, zusammen mit der Information, wo der defekte Code aufgetreten ist. Dann gibt die Funktion myHandler() eine freundliche Botschaft aus, die mithilfe der erhaltenen Fehlerinformationen erläutert, was schiefgegangen ist.
Hinweis: Es ist wichtig, daran zu denken, dass Parsefehler und schwerwiegende Fehler (fatal errors) aufgrund ihrer Natur den eigenen Error-Handler umgehen und mit dem standardmäßigen PHP-Error-Handling-Mechanismus angezeigt werden. Die Anzeige dieser Fehler kann mithilfe der Standardfunktion error_reporting() kontrolliert werden, wie oben beschrieben.
Listing F
Hier erzeugt der eigene Error-Handler jedes Mal dynamisch eine HTML-Fehlerseite, wenn ein Fehler auftritt. Die Fehlerinformation wird außerdem als E-Mail mithilfe von PHPs integrierter mail()-Funktion an den zuständigen Administrator geschickt.
Neu ist hier der Parameter $context, der yHandler() übergeben wird. Dieser fünfte Parameter ist eine optionale Ergänzung zu der Fehlerinformation, die myHandler() automatisch erhält, und enthält einen Schnappschuss des aktuellen Status der Variablen. Mit dieser Zusatzinformation kann der Administrator sich ein Bild vom Kontext des Fehlers machen, was die Debuggingzeit deutlich reduziert.
Listing G
Ähnlich wie beim vorherigen Beispiel erzeugt dieses Script eine Fehlerseite und protokolliert die Metadaten zu dem Fehler in einer Datei, so dass der Administrator diese Daten später auswerten kann. Die Daten werden im CSV-Format gespeichert, was die Analyse und Berichterstellung vereinfacht. Man beachte, dass in beiden Beispielen die Funktion die() am Ende des Error-Handling-Codes aufgerufen wird, um sicherzustellen, dass das Script nicht weiter ausgeführt wird.
Wie die obigen Beispiele illustrieren, ermöglicht ein eigener Error-Handler, Fehler in einem PHP-Script auf eine Weise zu behandeln, die den Anforderungen von Anwendung (und Benutzern) angemessen ist. Man kann seiner Kreativität hier freien Lauf lassen, wobei aber beachtet werden sollte, dass die zusätzliche Flexibilität mit komplexerem Programmcode und längeren Ausführungszeiten einhergeht.
URLs in diesem Artikel:[1] = http:/