Maison  >  Article  >  développement back-end  >  Comment PHP7 utilise set_error_handler et set_exception_handler pour gérer les mécanismes d'exception

Comment PHP7 utilise set_error_handler et set_exception_handler pour gérer les mécanismes d'exception

醉折花枝作酒筹
醉折花枝作酒筹avant
2021-05-31 09:17:252329parcourir

Cet article vous présentera comment PHP7 utilise set_error_handler et set_exception_handler pour gérer les mécanismes d'exception. Il a une certaine valeur de référence. Les amis dans le besoin peuvent s'y référer. J'espère qu'il sera utile à tout le monde.

Comment PHP7 utilise set_error_handler et set_exception_handler pour gérer les mécanismes d'exception

Pour des raisons historiques, PHP a été conçu à l'origine comme un langage orienté processus, donc la gestion des exceptions n'utilise pas le mécanisme try/catch comme Java, et les erreurs sont affichées directement . sur la page, ou enregistrées dans le journal des erreurs du serveur Web, et les erreurs PHP sont divisées en plusieurs niveaux, tels que E_ERROR, E_WARNING, E_PARSE, E_NOTICE, etc. Pour les erreurs graves comme E_ERROR, E_PARSE, PHP mettra directement fin au fichier. script d'opération.

Bien que pour la version php5, nous puissions utiliser set_error_handler pour enregistrer notre propre méthode de gestion des erreurs au lieu de la méthode de gestion des erreurs standard de PHP (sortie sur la page ou enregistrée dans le journal), mais certaines erreurs graves ne peuvent pas être gérées dans de cette façon. Pour y remédier, jetons un coup d'œil à l'introduction du manuel à cette méthode :

mixed set_error_handler ( callable $error_handler [, int $error_types = E_ALL | E_STRICT ] )

设置一个用户的函数(error_handler)来处理脚本中出现的错误。 

本函数可以用你自己定义的方式来处理运行中的错误, 例如,在应用程序中严重错误发生时,或者在特定条件下触发了一个错误(使用 trigger_error()),你需要对数据/文件做清理回收。 

重要的是要记住 error_types 里指定的错误类型都会绕过 PHP 标准错误处理程序, 除非回调函数返回了 FALSE。 error_reporting() 设置将不会起到作用而你的错误处理函数继续会被调用 —— 不过你仍然可以获取 error_reporting 的当前值,并做适当处理。 需要特别注意的是带 @ error-control operator 前缀的语句发生错误时,这个值会是 0。 

同时注意,在需要时你有责任使用 die()。 如果错误处理程序返回了,脚本将会继续执行发生错误的后一行。 

以下级别的错误不能由用户定义的函数来处理: E_ERROR、 E_PARSE、 E_CORE_ERROR、 E_CORE_WARNING、 E_COMPILE_ERROR、 E_COMPILE_WARNING,和在 调用 set_error_handler() 函数所在文件中产生的大多数 E_STRICT。

Le manuel dit très clairement que les erreurs telles que E_ERROR et E_PARSE ne peuvent pas être gérées par les utilisateurs. la démonstration de code (ci-dessous) L'exemple est exécuté avec php5.6)

<?php
 
//自定义的错误处理方法
function _error_handler($errno, $errstr ,$errfile, $errline)
{
    echo "错误编号errno: $errno<br>";
    echo "错误信息errstr: $errstr<br>";
    echo "出错文件errfile: $errfile<br>";
    echo "出错行号errline: $errline<br>";
}
 
set_error_handler(&#39;_error_handler&#39;, E_ALL | E_STRICT);  // 注册错误处理方法来处理所有错误
 
 
echo $foo[&#39;bar&#39;];  // 由于数组未定义,会产生一个notice级别的错误

Résultat de l'exécution :

错误编号errno: 8
错误信息errstr: Undefined variable: foo
出错文件errfile: D:\project\demo\demo.php
出错行号errline: 16

À ce stade, le message d'erreur n'est pas affiché directement sur la page comme d'habitude, mais est géré à notre manière. Si vous n'utilisez pas la fonction set_error_handler, le message d'erreur sera affiché comme ceci. Bien sûr, nous pouvons désactiver l'affichage des erreurs de PHP afin que l'erreur ne soit pas affichée directement sur la page.

Notice: Undefined variable: foo in D:\project\demo\demo.php on line 15

Ce mécanisme de traitement semble plutôt bon, mais comme mentionné ci-dessus, toutes les erreurs ne peuvent pas être gérées de cette façon. Modifiez le code ci-dessus comme suit :

<?php

//自定义的错误处理方法
function _error_handler($errno, $errstr ,$errfile, $errline)
{
    echo "错误编号errno: $errno<br>";
    echo "错误信息errstr: $errstr<br>";
    echo "出错文件errfile: $errfile<br>";
    echo "出错行号errline: $errline<br>";
}

set_error_handler(&#39;_error_handler&#39;, E_ALL | E_STRICT);  // 注册错误处理方法来处理所有错误


echo $foo[&#39;bar&#39;];  // 由于数组未定义,会产生一个notice级别的错误

trigger_error(&#39;人为触发一个错误&#39;, E_USER_ERROR); //人为触发错误

foobar(3, 5);   //调用未定义的方法将会产生一个Error级别的错误

Exécutez à nouveau :

错误编号errno: 8
错误信息errstr: Undefined variable: foo
出错文件errfile: D:\project\demo\demo.php
出错行号errline: 15
错误编号errno: 256
错误信息errstr: 人为产生触发一个错误
出错文件errfile: D:\project\demo\demo.php
出错行号errline: 17

Fatal error: Call to undefined function foobar() in D:\project\demo\demo.php on line 19
Comme nous nous y attendions, les deux premières erreurs ont été « détectées » et traitées par nos soins, mais la dernière erreur fatale n'a pas été traitée selon la fonction d'erreur que nous avons enregistrée et la méthode de traitement par défaut a toujours été utilisée. version php5. Un défaut majeur dans la manipulation. Il y a quelques nouveaux changements dans la méthode de gestion des exceptions après PHP7. Jetons un coup d'œil à l'introduction dans le manuel :

PHP 7 改变了大多数错误的报告方式。不同于传统(PHP 5)的错误报告机制,现在大多数错误被作为 Error 异常抛出。 

这种 Error 异常可以像 Exception 异常一样被第一个匹配的 try / catch 块所捕获。如果没有匹配的 catch 块,则调用异常处理函数(事先通过 set_exception_handler() 注册)进行处理。 如果尚未注册异常处理函数,则按照传统方式处理:被报告为一个致命错误(Fatal Error)。 

Error 类并非继承自 Exception 类,所以不能用 catch (Exception $e) { ... } 来捕获 Error。你可以用 catch (Error $e) { ... },或者通过注册异常处理函数( set_exception_handler())来捕获 Error。

Le mécanisme de gestion des erreurs de PHP7 est comme apprendre de Java, ce qui nous permet de gérer des erreurs de grande taille. problèmes d'échelle nous-mêmes. Pour la plupart des exceptions, voir l'exemple de code ci-dessous (le code suivant est exécuté en utilisant php7)

<?php

//自定义的错误处理方法
function _error_handler($errno, $errstr ,$errfile, $errline)
{
    echo "错误编号errno: $errno<br>";
    echo "错误信息errstr: $errstr<br>";
    echo "出错文件errfile: $errfile<br>";
    echo "出错行号errline: $errline<br>";
}

set_error_handler(&#39;_error_handler&#39;, E_ALL | E_STRICT);  // 注册错误处理方法来处理所有错误


try
{
    echo $foo[&#39;bar&#39;];  // 由于数组未定义,会产生一个notice级别的错误

    trigger_error(&#39;人为产生触发一个错误&#39;, E_USER_ERROR); //人为触发错误

    foobar(3, 5);   //调用未定义的方法将会产生一个Error级别的错误
}
catch (Error $e)
{
    echo "Error code: " . $e->getCode() . &#39;<br>&#39;;
    echo "Error message: " . $e->getMessage() . &#39;<br>&#39;;
    echo "Error file: " . $e->getFile() . &#39;<br>&#39;;
    echo "Error fileline: " . $e->getLine() . &#39;<br>&#39;;
}

Résultats d'exécution :

错误编号errno: 8
错误信息errstr: Undefined variable: foo
出错文件errfile: E:\project\demo\demo.php
出错行号errline: 17
错误编号errno: 256
错误信息errstr: 人为产生触发一个错误
出错文件errfile: E:\project\demo\demo.php
出错行号errline: 19
Error code: 0
Error message: Call to undefined function foobar()
Error file: E:\project\demo\demo.php
Error fileline: 21

De cette façon, différents types d'erreurs peuvent être gérés. par nous-mêmes, y compris des erreurs fatales. Si try/catch n'est pas utilisé, le message d'erreur de php7 est quand même quelque peu différent de celui de php5 :

错误编号errno: 8
错误信息errstr: Undefined variable: foo
出错文件errfile: E:\project\demo\demo.php
出错行号errline: 17
错误编号errno: 256
错误信息errstr: 人为触发一个错误
出错文件errfile: E:\project\demo\demo.php
出错行号errline: 19

Fatal error: Uncaught Error: Call to undefined function foobar() in E:\project\demo\demo.php:21 Stack trace: #0 {main} thrown in E:\project\demo\demo.php on line 21

La description de l'erreur fatale devient : Une erreur lancée n'a pas été interceptée.

Notez que la capture ici se limite à détecter les erreurs de la classe Error, et le manuel indique clairement que la classe Error n'est pas une sous-classe de la classe Exception, je souhaite donc détecter les erreurs d'exception dans le code. en même temps. N'est-ce pas impossible ? Eh bien, s'il vous plaît, regardez le code :

<?php

//自定义的错误处理方法
function _error_handler($errno, $errstr ,$errfile, $errline)
{
    echo "错误编号errno: $errno<br>";
    echo "错误信息errstr: $errstr<br>";
    echo "出错文件errfile: $errfile<br>";
    echo "出错行号errline: $errline<br>";
}

set_error_handler(&#39;_error_handler&#39;, E_ALL | E_STRICT);  // 注册错误处理方法来处理所有错误


try
{
    echo $foo[&#39;bar&#39;];  // 由于数组未定义,会产生一个notice级别的错误

    trigger_error(&#39;人为触发一个错误&#39;, E_USER_ERROR); //人为触发错误

    throw new Exception(&#39;This is a exception&#39;, 400);  //抛出一个Exception,看是否可以被catch

    foobar(3, 5);   //调用未定义的方法将会产生一个Error级别的错误
}
catch (Error $e)
{
    echo "Error code: " . $e->getCode() . &#39;<br>&#39;;
    echo "Error message: " . $e->getMessage() . &#39;<br>&#39;;
    echo "Error file: " . $e->getFile() . &#39;<br>&#39;;
    echo "Error fileline: " . $e->getLine() . &#39;<br>&#39;;
}

Résultat d'exécution :

错误编号errno: 8
错误信息errstr: Undefined variable: foo
出错文件errfile: E:\project\demo\demo.php
出错行号errline: 17
错误编号errno: 256
错误信息errstr: 人为触发一个错误
出错文件errfile: E:\project\demo\demo.php
出错行号errline: 19

Fatal error: Uncaught Exception: This is a exception in E:\project\demo\demo.php:21 Stack trace: #0 {main} thrown in E:\project\demo\demo.php on line 21

Alors, y a-t-il un moyen, en fait, de regarder le diagramme d'héritage ? dans le manuel


On peut voir que la classe Error et la classe Exception sont toutes deux des sous-classes de Throwable (en fait, la classe Error et la classe Exception implémentent la Interface jetable), de sorte que le code ci-dessus peut être optimisé comme :

<?php

//自定义的错误处理方法
function _error_handler($errno, $errstr ,$errfile, $errline)
{
    echo "错误编号errno: $errno<br>";
    echo "错误信息errstr: $errstr<br>";
    echo "出错文件errfile: $errfile<br>";
    echo "出错行号errline: $errline<br>";
}

set_error_handler(&#39;_error_handler&#39;, E_ALL | E_STRICT);  // 注册错误处理方法来处理所有错误


try
{
    echo $foo[&#39;bar&#39;];  // 由于数组未定义,会产生一个notice级别的错误

    trigger_error(&#39;人为触发一个错误&#39;, E_USER_ERROR); //人为触发错误

    if (mt_rand(1, 10) > 5)
    {
        throw new Exception(&#39;This is a exception&#39;, 400);  //抛出一个Exception,看是否可以被catch
    }
    else
    {
        foobar(3, 5);   //调用未定义的方法将会产生一个Error级别的错误
    }
}
catch (Throwable $e)
{
    echo "Error code: " . $e->getCode() . &#39;<br>&#39;;
    echo "Error message: " . $e->getMessage() . &#39;<br>&#39;;
    echo "Error file: " . $e->getFile() . &#39;<br>&#39;;
    echo "Error fileline: " . $e->getLine() . &#39;<br>&#39;;
}

Après l'avoir exécuté plusieurs fois, vous pouvez voir que, qu'il s'agisse d'une exception ou d'une erreur, il peut être intercepté et traité.

Si vous ne souhaitez pas que toutes les erreurs soient gérées avec try/catch, vous pouvez également utiliser set_exception_handler pour enregistrer une fonction de gestion des exceptions. De cette façon, lorsqu'une exception non interceptée se produit, le système appellera automatiquement la fonction. fonction de gestionnaire enregistré pour que nous puissions le gérer.

<?php

//自定义的错误处理方法
function _error_handler($errno, $errstr ,$errfile, $errline)
{
    echo "错误编号errno: $errno<br>";
    echo "错误信息errstr: $errstr<br>";
    echo "出错文件errfile: $errfile<br>";
    echo "出错行号errline: $errline<br>";
}

set_error_handler(&#39;_error_handler&#39;, E_ALL | E_STRICT);  // 注册错误处理方法来处理所有错误

function _exception_handler(Throwable $e)
{
    if ($e instanceof Error)
    {
        echo "catch Error: " . $e->getCode() . &#39;   &#39; . $e->getMessage() . &#39;<br>&#39;;
    }
    else
    {
        echo "catch Exception: " . $e->getCode() . &#39;   &#39; . $e->getMessage() . &#39;<br>&#39;;
    }
}

set_exception_handler(&#39;_exception_handler&#39;);    // 注册异常处理方法来捕获异常


echo $foo[&#39;bar&#39;];  // 由于数组未定义,会产生一个notice级别的错误

trigger_error(&#39;人为触发一个错误&#39;, E_USER_ERROR); //人为触发错误

if (mt_rand(1, 10) > 5)
{
    throw new Exception(&#39;This is a exception&#39;, 400);  //抛出一个Exception,看是否可以被catch
}
else
{
    foobar(3, 5);   //调用未定义的方法将会产生一个Error级别的错误
}
错误编号errno: 8
错误信息errstr: Undefined variable: foo
出错文件errfile: E:\project\demo\demo.php
出错行号errline: 29
错误编号errno: 256
错误信息errstr: 人为触发一个错误
出错文件errfile: E:\project\demo\demo.php
出错行号errline: 31
catch Error: 0 Call to undefined function foobar()


错误编号errno: 8
错误信息errstr: Undefined variable: foo
出错文件errfile: E:\project\demo\demo.php
出错行号errline: 29
错误编号errno: 256
错误信息errstr: 人为触发一个错误
出错文件errfile: E:\project\demo\demo.php
出错行号errline: 31
catch Exception: 400 This is a exception

À ce stade, nous pouvons à nouveau être confus par PHP7. Ceux qui sont traités par set_error_handler et lesquels sont traités par set_exception_handler. Le manuel n'explique pas clairement cela. D'après mon résumé, cela ne causera généralement pas. le script à terminer. Les erreurs seront gérées par set_error_handler, et les erreurs graves qui mettront fin à l'exécution du script seront renvoyées comme des erreurs, mais pas absolument. Le

E_USER_ERROR déclenché artificiellement ci-dessus est une erreur qui interrompra. l'exécution du script, mais ce n'est pas le cas. Elle n'est pas levée comme une exception d'erreur, mais est gérée par la méthode enregistrée par set_error_handler. Cela peut être dû au fait que ce type d'erreur est généré artificiellement par nous-mêmes, donc la gestion des erreurs de PHP7 est. encore quelque peu ambigu, et il ne nous convient pas de le gérer nous-mêmes.

Apprentissage recommandé :

Tutoriel vidéo php

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer