error_reporting()
In diesem Artikel besprechen wir Fehlerberichtsfunktionen in PHP und wie Entwickler damit Fehler erkennen und beheben können.
Einführung
Dieses Kapitel behandelt, wie PHP Fehler meldet: die Funktion error_reporting(), die steuert, welche Fehler PHP auslöst, die Direktiven display_errors und log_errors, die steuern, wohin diese Fehler gehen, sowie die unterstützenden Funktionen zur Fehlerbehandlung und -protokollierung. Am Ende wissen Sie, wie Sie die Fehlerberichterstattung für Entwicklung und Produktion unterschiedlich konfigurieren, und warum eine falsche Konfiguration einer der häufigsten Sicherheits- und Debugging-Fehler in PHP ist.
Warum Fehlerberichterstattung wichtig ist
PHP ist eine fehlertolerante, dynamisch typisierte Sprache: Viele Fehler, die in anderen Sprachen einen Kompilierungsfehler verursachen würden, treten hier zur Laufzeit als Warnungen, Hinweise oder Deprecation-Meldungen auf. Wenn Sie diese unterdrücken, kann fehlerhaftes Verhalten unbemerkt in die Produktion gelangen. Wenn Sie sie Endbenutzern anzeigen, können Sie Dateipfade, SQL-Abfragen und Stack-Traces an Angreifer weitergeben.
Eine gute Fehlerberichterstattung findet die richtige Balance für jede Umgebung:
- In der Entwicklung — zeigen Sie alles, lautstark, damit Sie Fehler sofort beim Schreiben erkennen.
- In der Produktion — zeigen Sie dem Benutzer nichts, aber protokollieren Sie alles in einer Datei zur späteren Analyse.
Fehlerstufen und Konstanten
PHP-Fehler werden nach Stufe bewertet. Jede Stufe ist eine vordefinierte Konstante, und Sie kombinieren sie mit bitweisen Operatoren. Die häufigsten Stufen:
| Konstante | Bedeutung |
|---|---|
E_ERROR | Schwerwiegender Laufzeitfehler; die Skriptausführung wird beendet. |
E_WARNING | Laufzeitwarnung; das Skript wird fortgesetzt. |
E_NOTICE | Hinweis (z. B. Verwendung einer undefinierten Variable). |
E_DEPRECATED | Verwendung einer Funktion, die in einer zukünftigen PHP-Version entfernt wird. |
E_USER_ERROR / E_USER_WARNING / E_USER_NOTICE | Stufen, die Sie selbst mit trigger_error() auslösen. |
E_ALL | Alle Fehler, Warnungen und Hinweise. |
Da diese Bit-Flags sind, kombinieren Sie sie mit | (einschließen), & (maskieren) und ~ (negieren):
// All errors EXCEPT notices and deprecation messages
error_reporting(E_ALL & ~E_NOTICE & ~E_DEPRECATED);
// Only fatal errors and warnings
error_reporting(E_ERROR | E_WARNING);Versionshinweis: Seit PHP 8.0 ist die Standard-
error_reporting-StufeE_ALL.E_STRICTwurde in 8.0 als veraltet markiert und in 8.4 entfernt, und seine Hinweise sind jetzt inE_ALLintegriert, sodass Sie es nicht mehr separat hinzufügen müssen.
Berichterstattung vs. Anzeige: zwei verschiedene Einstellungen
Eine häufige Quelle der Verwirrung ist, dass zwei unabhängige Schalter darüber entscheiden, ob Sie einen Fehler tatsächlich sehen:
error_reporting()— entscheidet, welche Stufen PHP erzeugt.display_errors— entscheidet, ob erzeugte Fehler in die Ausgabe gedruckt werden.
Sie müssen beide einschalten, um einen Fehler auf dem Bildschirm zu sehen. Das folgende Beispiel erzeugt einen E_ALL-Hinweis und gibt ihn aus, weil beide Schalter eingeschaltet sind:
<?php
error_reporting(E_ALL);
ini_set('display_errors', '1');
echo $undefined; // Warning: Undefined variable $undefinedWenn display_errors deaktiviert wäre, würde derselbe Hinweis weiterhin erzeugt (und könnte protokolliert werden), aber in der Seitenausgabe würde nichts erscheinen.
Die wichtigsten Fehlerberichtsfunktionen
error_reporting()
Legt fest, welche Fehlerstufen zur Laufzeit gemeldet werden, und gibt die vorherige Stufe zurück. Rufen Sie sie ohne Argument auf, um die aktuelle Einstellung zu lesen.
<?php
$old = error_reporting(E_ALL & ~E_NOTICE);
echo "Now reporting all errors except notices.\n";
echo "Previous level was: " . $old . "\n";ini_set()
Überschreibt eine php.ini-Direktive für die Dauer des aktuellen Skripts. Es ist das Laufzeit-Äquivalent zum Bearbeiten von php.ini, und damit können Sie display_errors, display_startup_errors und log_errors aus dem Code heraus umschalten.
<?php
// Development setup: show everything on screen
ini_set('display_errors', '1');
ini_set('display_startup_errors', '1');
error_reporting(E_ALL);Hinweis: display_errors kann schwerwiegende Parse-Fehler in derselben Datei nicht abfangen, da die gesamte Datei nicht kompiliert werden kann, bevor ini_set() ausgeführt wird. Setzen Sie die Direktive für solche Fälle direkt in php.ini.
set_error_handler()
Registriert einen Callback, der ausgeführt wird, wenn ein (nicht schwerwiegender) Fehler auftritt, und ermöglicht es Ihnen, das Standardverhalten von PHP zu ersetzen — zum Beispiel um Warnungen in Ausnahmen umzuwandeln oder sie als JSON für eine API zu formatieren. Der Callback empfängt die Fehlerstufe, die Nachricht, die Datei und die Zeile.
<?php
set_error_handler(function (int $errno, string $errstr, string $errfile, int $errline): bool {
echo "[$errno] $errstr in " . basename($errfile) . " on line $errline\n";
return true; // true = we handled it; PHP's internal handler is skipped
});
echo $undefined; // routed to our handler instead of the default messageWeitere Informationen finden Sie unter set_error_handler() zur vollständigen Signatur und zur Wiederherstellung des vorherigen Handlers.
error_log() und trigger_error()
error_log()sendet eine Nachricht an das konfigurierte PHP-Protokoll, eine bestimmte Datei oder eine E-Mail-Adresse — niemals an die Seitenausgabe. Dies ist der produktionssichere Weg zur Aufzeichnung von Problemen.trigger_error()löst einen selbst definierten Fehler aus (E_USER_*-Stufen), der dann durch dieselbeerror_reporting/Handler-Pipeline wie eingebaute Fehler fließt.
<?php
// Append a message to a specific log file (message type 3)
error_log("Payment gateway timed out", 3, "/var/log/php_errors.log");
// Raise a user-level warning that your handler / log can pick up
trigger_error("Cache miss for product 42", E_USER_WARNING);Erfahren Sie mehr unter error_log() und trigger_error().
Empfohlene Konfiguration pro Umgebung
Anstatt Einstellungen zu verstreuen, legen Sie sie am Anfang Ihrer Bootstrap-Datei fest.
<?php
// --- Development ---
error_reporting(E_ALL);
ini_set('display_errors', '1');
ini_set('display_startup_errors', '1');<?php
// --- Production ---
error_reporting(E_ALL); // still GENERATE everything...
ini_set('display_errors', '0'); // ...but never show it to users...
ini_set('log_errors', '1'); // ...log it instead.
ini_set('error_log', '/var/log/php_errors.log');Der Produktionsblock ermöglicht volle Sichtbarkeit durch Protokolle, ohne Besuchern etwas zu zeigen — die Konfiguration, die Sie auf einem Live-Server fast immer verwenden möchten.
Best Practices
- Betreiben Sie niemals die Produktion mit aktiviertem
display_errors. Geleakte Pfade und Stack-Traces sind ein Risiko für die Informationsoffenlegung. - Berichten Sie überall mit
E_ALL. Berichterstattung und Anzeige sind getrennt; das Unterdrücken von Stufen verbirgt nur Fehler. - Vermeiden Sie den
@-Fehlerunterdrückungsoperator. Er verbirgt Fehler an der Aufrufstelle und erschwert das Debugging erheblich; behandeln Sie den Zustand stattdessen explizit. - Fangen Sie was möglich als Ausnahmen ab. Bevorzugen Sie bei behebbaren Fehlern
try/catchgegenüber Fehlerhandlern. Siehe PHP Exceptions. - Verwenden Sie in größeren Anwendungen eine Protokollierungsbibliothek. Tools wie Monolog bieten Log-Stufen, Rotation und mehrere Ziele auf Basis von
error_log().
Fazit
Die Fehlerberichterstattung in PHP besteht aus drei Schichten: die Stufen mit error_reporting() wählen, das Ziel mit display_errors / log_errors festlegen und optional die Behandlung mit set_error_handler() und trigger_error() anpassen. Konfigurieren Sie sie bewusst — ausführlich auf dem Bildschirm während der Entwicklung, still aber protokolliert in der Produktion — und Sie erhalten schnelles Debugging, ohne Ihre Anwendung Benutzern oder Angreifern preiszugeben.
Weiterführende Lektüre: PHP Error handling · error_get_last() · try…catch.