2010-12-10 12 views
31

Nach the comment on this answer ist es möglich, Fatal Errors durch eine shutdown function zu fangen, die nicht mit set_error_handler() gefangen werden kann.Handle fatale Fehler in PHP mit register_shutdown_function()

Ich konnte jedoch nicht herausfinden, wie festgestellt werden kann, ob das Herunterfahren aufgrund eines schwerwiegenden Fehlers oder aufgrund des Endes des Skripts aufgetreten ist.

Darüber hinaus scheinen die Debug-Backtrace-Funktionen in der Shutdown-Funktion zu funktionieren, was es ziemlich wertlos macht, den Stack-Trace zu protokollieren, wo der Fatal Error aufgetreten ist.

Also meine Frage ist: Was ist der beste Weg, um auf Fatal Errors reagieren (vor allem undefinierte Funktionsaufrufe), während die Fähigkeit, eine ordnungsgemäße Backtrace erstellen?

Antwort

54

Dies funktioniert für mich:

function shutdown() { 
    $error = error_get_last(); 
    if ($error['type'] === E_ERROR) { 
     // fatal error has occured 
    } 
} 

register_shutdown_function('shutdown'); 

spl_autoload_register('foo'); 
// throws a LogicException which is not caught, so triggers a E_ERROR 

aber Sie wissen, dass es wahrscheinlich schon, aber nur um sicherzugehen: Sie können nicht von einer E_ERROR in irgendeiner Weise erholen.

Was den Backtrace, kann man nicht ... :(In den meisten Fällen von einem fatalen Fehler, vor allem Undefinierte Funktion Fehler, Sie nicht wirklich brauchen es. Die Datei/Zeile Aufzeigen, wo es aufgetreten ist Das Backtrace ist in diesem Fall nicht relevant.

+0

GREAT SNIPPET! Ich benutze auch "echo" Error MSG: [". $ Fehler ['Nachricht']."] In der Zeile: [". $ Fehler ['Zeile']."] \ R \ n ";' UPVOTED:) –

7

Eine Möglichkeit zur Unterscheidung zwischen schwerwiegendem Fehler und ordnungsgemäßem Herunterfahren der Anwendung mit der Funktion register_shutdown_function besteht darin, eine Konstante als letzte Zeile Ihres Programms zu definieren und dann zu überprüfen, ob die Konstante definiert ist:

function fatal_error() { 
if (! defined(PROGRAM_EXECUTION_SUCCESSFUL)) { 
     // fatal error has occurred 
    } 
} 

register_shutdown_function('fatal_error'); 

define('PROGRAM_EXECUTION_SUCCESSFUL', true); 

Wenn das Programm das Ende erreicht, könnte es Es ist kein fataler Fehler aufgetreten. Daher ist es bekannt, die Funktion nicht auszuführen, wenn die Konstante definiert ist.

error_get_last() ist ein Array mit allen Informationen über den schwerwiegenden Fehler, den Sie zum Debuggen benötigen, obwohl es kein Backtrace wie erwähnt haben wird.

Im Allgemeinen, wenn Ihr php-Programm einen schwerwiegenden Fehler (im Gegensatz zu einer Ausnahme) festgestellt hat, wollen Sie das Programm in die Luft gehen, damit Sie das Problem finden und beheben können. Ich habe register_shutdown_function gefunden, das für Produktionsumgebungen nützlich ist, in denen Sie Fehler melden möchten, aber eine Möglichkeit haben möchten, den Fehler im Hintergrund zu protokollieren, damit Sie darauf reagieren können. Sie können die Funktion auch verwenden, um den Benutzer im Falle eines solchen Fehlers auf eine freundliche HTML-Seite zu leiten, so dass Sie nicht nur eine leere Seite bereitstellen.

4

Gerade ein netter Trick, um die aktuellen error_handler Methode zu bekommen =)

<?php 
register_shutdown_function('__fatalHandler'); 
function __fatalHandler() 
{ 
    $error  = error_get_last(); 

    //check if it's a core/fatal error, otherwise it's a normal shutdown 
    if($error !== NULL && $error['type'] === E_ERROR) { 
     //Bit hackish, but the set_exception_handler will return the old handler 
     function fakeHandler() { } 
     $handler = set_exception_handler('fakeHandler'); 
     restore_exception_handler(); 
     if($handler !== null) { 
      call_user_func($handler, new ErrorException($error['message'], $error['type'], 0, $error['file'], $error['line'])); 
     } 
     exit; 
    } 
} 
?> 

auch wan't zu i beachten, dass, wenn Sie rufen

<?php 
ini_set('display_errors', false); 
?> 

Php stoppt den Fehler angezeigt wird, da sonst die Fehler Der Text wird vor dem Fehlerhandler an den Client gesendet.

-1

Ich benutze dafür "ob_start".

function fatal_error_handler($buffer) { 
    if (preg_match("|(Fatal error:)(.+)|", $buffer, $regs)) { 
     //Your code 
    } 
    return $buffer; 
} 
ob_start("fatal_error_handler"); 
+0

Dies Hinweise auf einen übergebenen Parameter, aber die Verwendung von Regex ist eine weniger effiziente Methode zur Überprüfung.Die akzeptierte Antwort ist klarer und effizienter. – pcnate