0251 / 590 837 15
info@a-coding-project.de

Basics: Fehlerbehandlung in PHP

Jeder macht Fehler, auch PHP. Man sollte wissen, wie man damit umzugehen hat um eine Website stabil am Laufen zu halten. Aus diesem Grund gibt es heute mal einen Basics-Artikel zum Thema Fehlerbehandlung mit PHP.

Fehler-Level (error_reporting)

In PHP gibt es mehrere Fehler-Stufen, bei denen je nach Schwere des Fehlers eine Meldung angezeigt oder ein Log-Eintrag geschrieben werden kann. Dabei gibt es folgende Level:

  • E_ERROR – Fatale Fehler, die eine Fortführung des Programms nicht erlauben
  • E_WARNING – Das Script wird trotzdem fortgeführt
  • E_PARSE – Das PHP-Script konnte nicht richtig geparsed werden (Syntax-Fehler)
  • E_NOTICE – Benachrichtigungen, dass es an einer Stelle zu Fehlern kommen könnte
  • E_STRICT – Vorschläge zur besseren Code-Qualität
  • E_DEPRECATED – Funktionen, die in zukünftigen PHP-Versionen abgeschafft werden
  • E_ALL – Alle Fehler

In der Entwicklungsumgebung ist es ratsam sich alle Fehler anzeigen zu lassen. So kann man den Code auf eine optimale Qualität bringen. Das geht zum Beispiel so:

<?php
  error_reporting(E_ALL);
?>

Fehler-Anzeige (display_errors)

Mit der Option display_errors wird angegeben, ob Fehler an den Browser ausgegeben werden oder nicht. Diesen Wert sollte man im Optimalfall in der Entwicklungsumgebung einschalten, aber im Live-Betrieb deaktiviert lassen. So gelangen interne Meldungen nicht nach außen. Hier kann man besser auf ein Log-System zurückgreifen (z.B. Graylog).

display_errors kann über die php.ini eingestellt werden. Diese kann man aber auch innerhalb von PHP umschalten. So ist es möglich, z.B. über einen Cookie die Fehlerausgabe auch im Live-Betrieb zu aktivieren:

<?php
  if($_COOKIE['display_errors'] === "ichbingeheim!")
  {
    ini_set('display_errors', '1');
  }

Selbst in den error_log schreiben

PHP bietet mit der error_log-Funktion einen einfachen Weg eigene Fehler zu loggen. Dabei wird im Standard an den PHP-Errorlog gesendet. Es ist aber auch möglich die Logs per E-Mail zu versenden oder in eine eigene Log-Datei zu stecken. Das sieht dann zum Beispiel so aus:

<?php
  error_log("R.I.P Datenbank", 3, "/var/log/database.log");

Der Vorteil der Nutzung dieser Log-Funktion ist, dass man bestehende Tools zur Auswertung von PHP-Fehlern verwenden kann und das im Gegensatz zu einer selbst erstellten Log-Funktion keine weiteren Komponenten benötigt werden (die ja auch fehlerhaft sein können).

Exceptions werfen und fangen

Eigene Fehler wirft man am besten mit Exceptions aus. Sie eignen sich hervorragend dazu, um zum auch dem Endbenutzer eine sinnvolle Meldung anzuzeigen. Eine Exception ist quasi ein Objekt, in dem bestimmte Informationen über einem Fehler gespeichert werden können. Es ist möglich, eigene Exception-Klassen zu erstellen, in dem man von der Exception-Klasse erbt. So kann man weitere Details hinzufügen und später auch leichter unterscheiden, um welche Art von Fehler es sich handelt.

Über den throw-Befehl können solche Exceptions geworfen werden. Das bedeutet, dass die Ausführung des Codes an der Stelle unterbrochen wird und in den nächstgelegenen Catch-Block gesprungen wird. Ist ein solcher nicht vorhanden, wird im Standard die Exception als PHP-Fehler an den Browser gesendet.

<?php
  try
  {
    throw new Exception("Oh nein, ein Fehler!");
    echo "Alles ok!";
  }
  catch(Exception $ex)
  {
    print_r($ex);
  }

Hier wird eine neue Exception erstellt und direkt geworfen. Das „Alles ok!“ wird dabei nicht mehr ausgegeben. Stattdessen wird der Catch-Block aufgerufen, in dem mit print_r der Fehler ausgegeben wird.

Nun können wir auch unsere eigene Exception-Klasse erstellen, das könnte dann zum Beispiel so aussehen:

<?php
  class MyException extends Exception
  {
    public $author = null;
  }

  try
  {
    $ex = new MyException();
    $ex->author = "Stefan";
    throw $ex;
    echo "Alles ok!";
  }
  catch(MyException $ex)
  {
    echo $ex->author." hat's kaputt gemacht!";
  }
  catch(Exception $ex)
  {
    print_r($ex);
  }

Tritt nun eine Exception vom Typ „MyException“ auf, wird der erste catch-Block genommen, für alle anderen dann der zweite Teil.
Innerhalb einer solchen Exception-Klasse kann man zum Beispiel auch direkt die Fehlerausgabe integrieren. Durch geschickte Vererbung kann man hier schöne Sachen machen.

Fehler unterdrücken – Der @-Operator

Der leichteste Weg, um Fehler mit PHP zu umgehen, ist einfach ein @ vor der Funktion zu schreiben. Alle Fehler werden ignoriert:

<?php
  @mkdir('verzeichnis');

Konnte nun ein Verzeichnis nicht erstellt werden, wird der Code trotzdem weiter ausgeführt, der Fehler wird schlichtweg ignoriert. Durch die Einfachheit ist der @-Operator der perfekte Begleiter für alle faulen Programmierer. Aus dieser Einfachheit resultiert aber auch Folgendes:

  • Fehler können nicht immer sofort erkannt werden (langes Suchen, an welcher Stelle ein Fehler auftritt)
  • Die Performance des @-Parameters ist extrem schlecht

Aus diesem Grund sollte man das @ möglichst wenig benutzen. In der Regel kann man mit If-Abfragen viele unnütze @ abfangen. An manchen Stellen kann es aber auch Sinn machen, dass @ zu verwenden. Zum Beispiel wenn Fehler einfach vorab nicht abgefangen werden können (z.B. beim Aufbau von Datenbankverbindungen). In dem Fall kann man dann am besten mit einer If-Bedingung um den Befehl prüfen, ob diese erfolgreich war. Bei aktivierten track_errors kann man im Fehlerfall über die Variable $php_errormsg an die Fehlermeldung kommen.