2010-12-10 17 views
31

De acuerdo con the comment on this answer es posible detectar los errores fatales a través de un shutdown function que no se puede capturar utilizando set_error_handler().Manejar errores fatales en PHP usando register_shutdown_function()

Sin embargo, no pude encontrar la manera de determinar si el cierre ha ocurrido debido a un error fatal o debido a que el script ha llegado a su fin.

Además, las funciones de seguimiento de depuración parecen haber desaparecido en la función de apagado, lo que hace que no valga la pena registrar el seguimiento de la pila donde se produjo el error fatal.

Así que mi pregunta es: ¿cuál es la mejor manera de reaccionar contra los errores fatales (especialmente las llamadas a funciones no definidas) mientras se mantiene la capacidad de crear una traza inversa adecuada?

Respuesta

54

Esto funciona para mí:

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 

Sin embargo, probablemente lo saben ya, pero sólo para asegurarse de: usted no puede recuperarse de una E_ERROR de ninguna manera.

En cuanto a la traza, no se puede ... :(En la mayoría de los casos de un error fatal, especialmente Undefined función errores, que en realidad no lo necesitan. Pinpointing el archivo/línea donde se produjo es Bastante. La traza inversa es irrelevante en ese caso.

+0

GREAT SNIPPET! También uso 'echo" Error MSG: [". $ Error ['message']."] On line: [". $ Error ['line']."] \ R \ n ";' UPVOTED:) –

7

Una manera de distinguir entre el error fatal y el apagado apropiado de la aplicación con la función register_shutdown_function es definir una constante como la última línea de su programa, y ​​luego verificar si la constante está definida:

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

register_shutdown_function('fatal_error'); 

define('PROGRAM_EXECUTION_SUCCESSFUL', true); 

Si el programa llega al final, podría no ha encontrado un error fatal, por lo que sabemos que no se ejecutará la función si se define la constante.

error_get_last() es una matriz con toda la información sobre el error fatal que debe ser depurada, aunque no tendrá una traza inversa, como se ha mencionado.

Generalmente, si su programa php ha encontrado un error fatal (a diferencia de una excepción), desea que el programa explote para que pueda encontrar y solucionar el problema. He descubierto que register_shutdown_function es útil para entornos de producción en los que desea informes de errores, pero desea alguna manera de registrar el error en segundo plano para que pueda responder. También puede utilizar la función para dirigir al usuario a una página html amigable en caso de que se produzca dicho error, de modo que no solo muestre una página en blanco.

4

Tan sólo un buen truco para conseguir el método actual gestor_errores =)

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

También me wa no tener en cuenta que si usted llama

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

PHP deja de mostrar el error, de lo contrario el error el texto se enviará al cliente antes de su manejador de errores

-1

Utilizo "ob_start" para esto.

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

Esto insinúa que se pasa un parámetro, pero usar regex es un método de comprobación menos eficiente.La respuesta aceptada es más clara y más eficiente. – pcnate

Cuestiones relacionadas