2010-12-10 8 views
31

Selon the comment on this answer, il est possible d'attraper les erreurs fatales via un shutdown function qui ne peut pas être intercepté en utilisant set_error_handler().Gérer les erreurs fatales dans PHP en utilisant register_shutdown_function()

Toutefois, je n'ai pas pu déterminer comment déterminer si l'arrêt s'est produit en raison d'une erreur fatale ou en raison de la fin du script.

De plus, les fonctions de backtrace de débogage semblent être supprimées dans la fonction shutdown, ce qui rend la journalisation de la trace de la pile où l'erreur fatale s'est produite inutile. Donc, ma question est: quelle est la meilleure façon de réagir aux erreurs fatales (en particulier les appels de fonctions non définis) tout en gardant la possibilité de créer un backtrace approprié?

Répondre

54

Cela fonctionne pour moi:

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 

Cependant, vous le savez probablement déjà, mais juste pour se assurer: vous ne pouvez pas récupérer d'un E_ERROR de quelque façon. Comme pour le backtrace, vous ne pouvez pas ... :(Dans la plupart des cas d'une erreur fatale, en particulier Des erreurs non définies de la fonction, vous n'en avez pas vraiment besoin.

+0

GRAND SNIPPET! J'utilise aussi 'echo" Erreur MSG: [". $ Error ['message']."] En ligne: [". $ Error ['line']."] \ R \ n ";' UPVOTED:) –

7

Une façon de distinguer entre une erreur fatale et une fermeture d'application correcte avec la fonction register_shutdown_ consiste à définir une constante comme dernière ligne de votre programme, puis à vérifier si la constante est définie:

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

register_shutdown_function('fatal_error'); 

define('PROGRAM_EXECUTION_SUCCESSFUL', true); 

Si le programme atteint la fin, il pourrait N'a pas rencontré une erreur fatale, donc nous savons ne pas exécuter la fonction si la constante est définie. Error_get_last() est un tableau avec toutes les informations concernant l'erreur fatale que vous devriez avoir besoin de déboguer, bien qu'il n'ait pas de backtrace, comme cela a été mentionné.

Généralement, si votre programme PHP a rencontré une erreur fatale (par opposition à une exception), vous voulez que le programme explose afin que vous puissiez trouver et résoudre le problème. J'ai trouvé la fonction register_shutdown_function utile pour les environnements de production dans lesquels vous voulez désactiver les rapports d'erreurs, mais vous voulez un moyen de consigner l'erreur en arrière-plan pour pouvoir y répondre. Vous pouvez également utiliser la fonction pour diriger l'utilisateur vers une page HTML conviviale dans le cas d'une telle erreur afin que vous ne diffusiez pas simplement une page vierge.

4

Juste une belle astuce pour obtenir la méthode error_handler courant =)

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

i wan't également de noter que si vous appelez

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

Php cesse d'afficher l'erreur, sinon l'erreur le texte sera envoyé au client avant votre gestionnaire d'erreur

-1

J'utilise "ob_start" pour cela.

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

indications sur un paramètre étant passé, mais en utilisant regex est une méthode de vérification moins efficace.La réponse acceptée est à la fois plus claire et plus efficace. – pcnate

Questions connexes