Wie kann ich parse & fatal Fehler mit einem custom Fehlerhandler behandeln?
Einfache Antwort: Das kannst du nicht. Siehe das Handbuch :
Die folgenden Fehlertypen können mit einer benutzerdefinierten Funktion nicht behandelt werden: E_ERROR, E_PARSE, E_CORE_ERROR, E_CORE_WARNING, E_COMPILE_ERROR, E_COMPILE_WARNING und der größte Teil von E_STRICT, der in der Datei ausgelöst wird, in der set_error_handler () aufgerufen wird.
Für jeden anderen Fehler können Sie set_error_handler()
verwenden.
BEARBEITEN:
Da es den Anschein hat, dass es zu diesem Thema einige Diskussionen gibt, was die Verwendung von register_shutdown_function
, wir sollten einen Blick auf die Definition der Behandlung werfen: Die Behandlung eines Fehlers bedeutet für mich, den Fehler abzufangen und auf eine Weise zu reagieren, die für den Benutzer "nett" ist und die zugrunde liegenden Daten (Datenbanken, Dateien, Webdienste usw.).
Mit register_shutdown_function
Sie können einen Fehler nicht in dem Code behandeln, in dem er aufgerufen wurde, was bedeutet, dass der Code an dem Punkt, an dem der Fehler auftritt, immer noch nicht mehr funktioniert. Sie können dem Benutzer jedoch anstelle einer weißen Seite eine Fehlermeldung anzeigen, aber Sie können beispielsweise nichts zurücksetzen, was Ihr Code vor dem Fehlschlagen getan hat.
Tatsächlich können Sie mit Analyse- und schwerwiegenden Fehlern umgehen. Es ist richtig, dass die mit set_error_handler () definierte Fehlerbehandlungsfunktion nicht aufgerufen wird. Die Möglichkeit besteht darin, eine Shutdown-Funktion mit register_shutdown_function () zu definieren. Hier ist, was ich auf meiner Website arbeite:
Datei prepend.php (Diese Datei wird automatisch allen PHP-Skripten vorangestellt). Im Folgenden finden Sie Tipps zum Voranstellen von Dateien an PHP.
set_error_handler("errorHandler");
register_shutdown_function("shutdownHandler");
function errorHandler($error_level, $error_message, $error_file, $error_line, $error_context)
{
$error = "lvl: " . $error_level . " | msg:" . $error_message . " | file:" . $error_file . " | ln:" . $error_line;
switch ($error_level) {
case E_ERROR:
case E_CORE_ERROR:
case E_COMPILE_ERROR:
case E_PARSE:
mylog($error, "fatal");
break;
case E_USER_ERROR:
case E_RECOVERABLE_ERROR:
mylog($error, "error");
break;
case E_WARNING:
case E_CORE_WARNING:
case E_COMPILE_WARNING:
case E_USER_WARNING:
mylog($error, "warn");
break;
case E_NOTICE:
case E_USER_NOTICE:
mylog($error, "info");
break;
case E_STRICT:
mylog($error, "debug");
break;
default:
mylog($error, "warn");
}
}
function shutdownHandler() //will be called when php script ends.
{
$lasterror = error_get_last();
switch ($lasterror['type'])
{
case E_ERROR:
case E_CORE_ERROR:
case E_COMPILE_ERROR:
case E_USER_ERROR:
case E_RECOVERABLE_ERROR:
case E_CORE_WARNING:
case E_COMPILE_WARNING:
case E_PARSE:
$error = "[SHUTDOWN] lvl:" . $lasterror['type'] . " | msg:" . $lasterror['message'] . " | file:" . $lasterror['file'] . " | ln:" . $lasterror['line'];
mylog($error, "fatal");
}
}
function mylog($error, $errlvl)
{
...do whatever you want...
}
PHP ruft die Funktion errorHandler () auf, wenn er einen Fehler in einem der Skripte entdeckt. Wenn der Fehler das sofortige Herunterfahren des Skripts erzwingt, wird der Fehler von der Funktion shutdownHandler () behandelt.
Dies funktioniert auf der Site, die ich gerade entwickle. Ich habe es noch nicht in der Produktion getestet. Aber es fängt momentan alle Fehler auf, die ich während der Entwicklung finde.
Ich glaube, es besteht die Gefahr, dass jeder Fehler zweimal von jeder Funktion abgefangen wird. Dies kann passieren, wenn ein Fehler, den ich in der Funktion shutdownHandler () behandle, auch von der Funktion errorHandler () abgefangen wurde.
TODO's:
1 - Ich muss an einer besseren log () - Funktion arbeiten, um Fehler ordnungsgemäß behandeln zu können. Da ich mich noch in der Entwicklung befinde, protokolliere ich den Fehler im Grunde genommen in einer Datenbank und speichere ihn auf dem Bildschirm.
2 - Implementieren Sie die Fehlerbehandlung für alle MySQL-Aufrufe.
3 - Implementieren Sie die Fehlerbehandlung für meinen Javascript-Code.
WICHTIGE HINWEISE:
1 - Ich verwende die folgende Zeile in meiner php.ini, um das obige Skript automatisch allen PHP-Skripten voran zu stellen:
auto_prepend_file = "/homepages/45/d301354504/htdocs/hmsee/cgi-bin/errorhandling.php"
es funktioniert gut.
2 - Ich protokolliere und löse alle Fehler, einschließlich E_STRICT-Fehler. Ich glaube an die Entwicklung eines sauberen Codes. Während der Entwicklung hat meine php.ini-Datei die folgenden Zeilen:
track_errors = 1
display_errors = 1
error_reporting = 2147483647
html_errors = 0
Wenn ich live gehe, werde ich display_errors auf 0 ändern, um das Risiko zu verringern, dass meine Benutzer hässliche PHP Fehlermeldungen sehen.
Ich hoffe das hilft jemandem.
Sie können diese Fehler mit folgendem Code verfolgen:
(Parse-Fehler können nur abgefangen werden, wenn sie in anderen Skriptdateien über include()
oder require()
oder durch Einfügen dieses Codes in einen auto_prepend_file
wie andere Antworten erwähnt haben.)
function shutdown() {
$isError = false;
if ($error = error_get_last()){
switch($error['type']){
case E_ERROR:
case E_CORE_ERROR:
case E_COMPILE_ERROR:
case E_USER_ERROR:
$isError = true;
break;
}
}
if ($isError){
var_dump ($error);//do whatever you need with it
}
}
register_shutdown_function('shutdown');
Aus den PHP.net-Kommentaren auf der Seite http://www.php.net/manual/en/function.set-error-handler.php
Ich habe festgestellt, dass einige Leute hier erwähnt haben, dass Sie keine Analysefehler erfassen können (Typ 4, E_PARSE). Das ist nicht wahr. So mache ich es. Ich hoffe das hilft jemandem.
1) Erstellen Sie eine "auto_prepend.php" -Datei im Web-Stammverzeichnis und fügen Sie Folgendes hinzu:
<?php
register_shutdown_function('error_alert');
function error_alert()
{
if(is_null($e = error_get_last()) === false)
{
mail('[email protected]', 'Error from auto_prepend', print_r($e, true));
}
}
?>
2) Fügen Sie dann diese "php_value auto_prepend_file /www/auto_prepend.php" zu Ihrer .htaccess-Datei im Web-Stammverzeichnis hinzu.
- stellen Sie sicher, dass Sie die E-Mail-Adresse und den Pfad zur Datei ändern.
Nach meiner Erfahrung können Sie alle Arten von Fehlern abfangen, die Standardfehlermeldung ausblenden und eine eigene Fehlermeldung anzeigen (wenn Sie möchten). Unten sind die Dinge aufgelistet, die Sie brauchen.
1) Ein Skript der ersten/obersten Ebene, nennen wir es index.php
, In dem Sie Ihre benutzerdefinierten Fehlerbehandlungsfunktionen speichern. Benutzerdefinierte Fehlerfunktions-Handler müssen oben bleiben, damit sie Fehler unterhalb von ihnen erkennen. Mit "unten" meine ich in eingeschlossenen Dateien.
2) Die Annahme, dass dieses Top-Skript fehlerfrei ist, muss stimmen! Dies ist sehr wichtig. Sie können keine schwerwiegenden Fehler in index.php
abfangen, wenn sich Ihre benutzerdefinierte Fehlerbehandlungsfunktion in index.php
befindet.
3) PHP-Direktiven (müssen auch in index.php
Enthalten sein) set_error_handler("myNonFatalErrorHandler");
#, um nicht schwerwiegende Fehler abzufangen register_shutdown_function('myShutdown');
#, um schwerwiegende Fehler abzufangen ini_set('display_errors', false);
# Um Fehler zu verbergen, die dem Benutzer von PHP angezeigt werden ini_set('log_errors',FALSE);
# Angenommen, wir protokollieren die Fehler selbst ini_set('error_reporting', E_ALL);
#Wir möchten alle Fehler melden
während der Produktion (wenn ich mich nicht irre) können wir ini_set('error_reporting', E_ALL);
so lassen, wie es ist, um Fehler zu protokollieren. Gleichzeitig wird ini_set('display_errors', false);
sicherstellen, dass keine Fehler angezeigt werden an den Benutzer.
Bezüglich des tatsächlichen Inhalts der beiden Funktionen, von denen ich spreche, myNonFatalErrorHandler
und myShutdown
, füge ich hier keinen detaillierten Inhalt ein, um die Dinge einfach zu halten. Darüber hinaus haben die anderen Besucher zahlreiche Beispiele genannt. Ich zeige nur eine sehr einfache Idee.
function myNonFatalErrorHandler($v, $m, $f, $l, $c){
$some_logging_var_arr1[]="format $v, $m, $f, ".$err_lvl[$l].", $c the way you like";
//You can display the content of $some_logging_var_arr1 at the end of execution too.
}
function myShutdown()
{
if( ($e=error_get_last())!==null ){
$some_logging_var_arr2= "Format the way you like:". $err_level[$e['type']].$e['message'].$e['file'].$e['line'];
}
//display $some_logging_var_arr2 now or later, e.g. from a custom session close function
}
wie für $ err_lvl kann es sein:
$err_lvl = array(E_ERROR=>'E_ERROR', E_CORE_ERROR=>'E_CORE_ERROR', E_COMPILE_ERROR=>'E_COMPILE_ERROR', E_USER_ERROR=>'E_USER_ERROR', E_PARSE=>'E_PARSE', E_RECOVERABLE_ERROR=>'E_RECOVERABLE_ERROR', E_WARNING=>'E_WARNING', E_CORE_WARNING=>'E_CORE_WARNING', E_COMPILE_WARNING=>'E_COMPILE_WARNING',
E_USER_WARNING=>'E_USER_WARNING', E_NOTICE=>'E_NOTICE', E_USER_NOTICE=>'E_USER_NOTICE',E_STRICT=>'E_STRICT');
Das Skript mit Analysefehler wird immer unterbrochen und kann nicht bearbeitet werden. Wenn das Skript also direkt oder mit include/require aufgerufen wird, können Sie nichts tun. Aber wenn es von AJAX, Flash oder auf andere Weise aufgerufen wird, gibt es is eine Problemumgehung, um Analysefehler zu erkennen.
Ich brauchte dies, um swfupload Skript zu behandeln. Swfupload ist ein Flash, der das Hochladen von Dateien und jedes Mal, wenn eine Datei hochgeladen wird, den Aufruf von PHP handling script to filedata - aber es gibt keine Browser-Ausgabe, daher die PHP = handling script benötigt diese Einstellungen zum Debuggen:
if(!isset($_SESSION["swfupload"])) echo "parse error";
Anmerkung 1null
bedeutet is not set
Bis isset()