webentwicklung-frage-antwort-db.com.de

PHP: Benutzerdefinierte Fehlerbehandlung - Behandlung von Analyse- und schwerwiegenden Fehlern

Wie kann ich parse & fatal Fehler mit einem custom Fehlerhandler behandeln?

54

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.

27
Dan Soap

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.

69
jdias

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');
30
Deniss Kozlovs

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.
11
Creativehavoc

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');
5
Melsi

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:

  • Warnungen und Hinweise ob_start (); am Anfang und speichern Sie den Inhalt in der Sitzung von ob_get_contents (); am Ende des Bearbeitungsskripts: Dies kann von einem anderen Skript im Browser angezeigt werden
  • fatale Fehler register_shutdown_function (), um die Sitzung mit dem gleichen Trick wie oben festzulegen
  • Fehler analysieren Wenn sich ob_get_contents () am Ende des Behandlungsskripts befindet und ein Fehler beim Analysieren aufgetreten ist, wird die Sitzung nicht gefüllt (er ist null). Das Debugging-Skript kann folgendermaßen vorgehen: if(!isset($_SESSION["swfupload"])) echo "parse error";

Anmerkung 1null bedeutet is not set Bis isset()

4
Jan Turoň