2010-12-10 8 views
31

Według the comment on this answer możliwe jest przechwytywanie błędów krytycznych za pomocą shutdown function, które nie mogą zostać przechwycone za pomocą set_error_handler().Obsługa błędów krytycznych w PHP przy użyciu register_shutdown_function()

Jednak nie mogłem dowiedzieć się, jak ustalić, czy nastąpiło wyłączenie z powodu błędu krytycznego lub z powodu zakończenia działania skryptu.

Ponadto funkcje śledzenia wstecznego debugowania wydają się być nieczynne w funkcji wyłączania, co czyni je zupełnie bezwartościowymi do rejestrowania śladu stosu w miejscu wystąpienia błędu krytycznego.

Moje pytanie brzmi: jaki jest najlepszy sposób reagowania w przypadku błędów krytycznych (szczególnie niezdefiniowanych wywołań funkcji), zachowując przy tym możliwość tworzenia prawidłowego śledzenia wstecznego?

Odpowiedz

54

Działa to dla mnie:

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 

jednak pewnie wiedzą już, ale tylko upewnić: nie można odzyskać z E_ERROR w jakikolwiek sposób.

chodzi o backtrace, nie możesz ... :(W większości przypadków fatalnym błędem, zwłaszcza niezdefiniowane funkcyjne błędy, tak naprawdę nie jest to potrzebne. Dokładne wskazanie pliku/linię, gdzie wystąpił jest W takim przypadku ślad cofnięcia jest nieistotny:

+0

WSPANIAŁY SNIPPET! Używam również "echo" Error MSG: [". $ Error ['message']." On line: [". $ Error ['line'].] \ R \ n"; UPVOTED:) –

7

Jednym ze sposobów odróżnienia błędu krytycznego od właściwego zamknięcia aplikacji za pomocą funkcji register_shutdown_function jest zdefiniowanie stałej jako ostatniej linii programu, a następnie sprawdzenie, czy stała jest zdefiniowana:

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

register_shutdown_function('fatal_error'); 

define('PROGRAM_EXECUTION_SUCCESSFUL', true); 

Jeśli program osiągnie koniec, może nie napotkał błędu krytycznego, więc wiemy, że funkcja nie jest uruchamiana, jeśli stała jest zdefiniowana.

error_get_last() to tablica zawierająca wszystkie informacje dotyczące błędu krytycznego, który powinien być potrzebny do debugowania, chociaż nie będzie miał śladu wstecznego, jak już wspomniano.

Ogólnie, jeśli twój program php napotkał błąd krytyczny (w przeciwieństwie do wyjątku), chcesz, aby program się wysadził, abyś mógł znaleźć i naprawić problem. Znalazłem funkcję register_shutdown_function przydatną w środowiskach produkcyjnych, w których chcesz raportować o błędach, ale chcesz w jakiś sposób zarejestrować błąd w tle, aby móc na nie odpowiedzieć. Możesz także użyć tej funkcji, aby skierować użytkownika na przyjazną stronę html w przypadku wystąpienia takiego błędu, aby nie wyświetlać pustej strony.

4

prostu ładny podstęp, aby uzyskać aktualną metodę error_handler =)

<?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; 
    } 
} 
?> 

Również wa nie zauważyć, że jeśli zadzwonisz

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

PHP zatrzymuje wyświetlanie błędu, w przeciwnym razie błędu tekst zostanie wysłany do klienta przed obsługą błędu

-1

Używam do tego "ob_start".

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

To podpowiedzi na przekazywany parametr, ale użycie regex jest mniej skuteczną metodą sprawdzania.Przyjęta odpowiedź jest zarówno jaśniejsza, jak i bardziej skuteczna. – pcnate