This article will introduce to you how PHP7 uses set_error_handler and set_exception_handler to handle exception mechanisms. It has certain reference value. Friends in need can refer to it. I hope it will be helpful to everyone.
Due to historical reasons, PHP was originally designed as a process-oriented language, so exception handling does not use the try/catch mechanism like Java, and errors are displayed directly. to the page, or recorded in the error log of the web server, and PHP errors are divided into many levels, such as E_ERROR, E_WARNING, E_PARSE, E_NOTICE, etc. For serious errors like E_ERROR, E_PARSE, PHP will directly terminate the script of operation.
Although for the php5 version, we can use set_error_handler to register our own error handling method instead of PHP's standard error handling method (output to the page or recorded to the log), but some serious errors cannot be handled in this way. To deal with it, let’s take a look at the manual’s introduction to this method:
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。
The manual says very clearly that errors such as E_ERROR and E_PARSE cannot be handled by users. Let’s take a look at the code demonstration (below) The example is run with 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('_error_handler', E_ALL | E_STRICT); // 注册错误处理方法来处理所有错误 echo $foo['bar']; // 由于数组未定义,会产生一个notice级别的错误
Running results:
错误编号errno: 8 错误信息errstr: Undefined variable: foo 出错文件errfile: D:\project\demo\demo.php 出错行号errline: 16
At this time, the error message is not output directly to the page as usual, but is handled in our own way. If you do not use the set_error_handler function, the error message will be displayed like this. Of course, we can turn off the error display of PHP so that the error will not be displayed directly on the page.
Notice: Undefined variable: foo in D:\project\demo\demo.php on line 15
This processing mechanism seems pretty good, but as mentioned above not all errors can be handled this way. Modify the above code as follows:
<?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('_error_handler', E_ALL | E_STRICT); // 注册错误处理方法来处理所有错误 echo $foo['bar']; // 由于数组未定义,会产生一个notice级别的错误 trigger_error('人为触发一个错误', E_USER_ERROR); //人为触发错误 foobar(3, 5); //调用未定义的方法将会产生一个Error级别的错误
Run again:
错误编号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
As we expected, the first two errors were "caught" and processed by us, but the last Fatal error was not processed according to the error function we registered, and the default processing method was still used. This is also an error in the php5 version. A major flaw in handling. There are some new changes in the exception handling method after PHP7. Let’s take a look at the introduction in the manual:
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。
This error handling mechanism of PHP7 is like learning java, which allows us to handle large-scale problems ourselves. For most exceptions, see the code example below (the following code is run using 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('_error_handler', E_ALL | E_STRICT); // 注册错误处理方法来处理所有错误 try { echo $foo['bar']; // 由于数组未定义,会产生一个notice级别的错误 trigger_error('人为产生触发一个错误', E_USER_ERROR); //人为触发错误 foobar(3, 5); //调用未定义的方法将会产生一个Error级别的错误 } catch (Error $e) { echo "Error code: " . $e->getCode() . '<br>'; echo "Error message: " . $e->getMessage() . '<br>'; echo "Error file: " . $e->getFile() . '<br>'; echo "Error fileline: " . $e->getLine() . '<br>'; }
Running results:
错误编号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
In this way, different types of errors can be handled by ourselves, including fatal errors. If try / catch is not used, the error message of php7 is still somewhat different from that of 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
The description of the fatal error becomes: An Error thrown was not caught.
Note that the catch here is limited to catching only errors of the Error class, and the manual clearly states that the Error class is not a subclass of the Exception class. So I want to catch the Exception errors in the code at the same time. Isn’t it impossible? Please look at the 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('_error_handler', E_ALL | E_STRICT); // 注册错误处理方法来处理所有错误 try { echo $foo['bar']; // 由于数组未定义,会产生一个notice级别的错误 trigger_error('人为触发一个错误', E_USER_ERROR); //人为触发错误 throw new Exception('This is a exception', 400); //抛出一个Exception,看是否可以被catch foobar(3, 5); //调用未定义的方法将会产生一个Error级别的错误 } catch (Error $e) { echo "Error code: " . $e->getCode() . '<br>'; echo "Error message: " . $e->getMessage() . '<br>'; echo "Error file: " . $e->getFile() . '<br>'; echo "Error fileline: " . $e->getLine() . '<br>'; }
Running results:
错误编号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
Is there any way? In fact, look at the inheritance diagram in the manual
It can be seen that the Error class and the Exception class are both subclasses of Throwable (actually both the Error class and the Exception class implement the Throwable interface), so the above code can be optimized as:
<?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('_error_handler', E_ALL | E_STRICT); // 注册错误处理方法来处理所有错误 try { echo $foo['bar']; // 由于数组未定义,会产生一个notice级别的错误 trigger_error('人为触发一个错误', E_USER_ERROR); //人为触发错误 if (mt_rand(1, 10) > 5) { throw new Exception('This is a exception', 400); //抛出一个Exception,看是否可以被catch } else { foobar(3, 5); //调用未定义的方法将会产生一个Error级别的错误 } } catch (Throwable $e) { echo "Error code: " . $e->getCode() . '<br>'; echo "Error message: " . $e->getMessage() . '<br>'; echo "Error file: " . $e->getFile() . '<br>'; echo "Error fileline: " . $e->getLine() . '<br>'; }
You can see if you run it multiple times, whether it is an Exception or an Error, it can be captured and processed.
If you don’t want all errors to be handled with try/catch, you can also use set_exception_handler to register an exception handling function. In this way, when an uncaught exception occurs, the system will automatically call the registered handler function for us to handle it. .
<?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('_error_handler', E_ALL | E_STRICT); // 注册错误处理方法来处理所有错误 function _exception_handler(Throwable $e) { if ($e instanceof Error) { echo "catch Error: " . $e->getCode() . ' ' . $e->getMessage() . '<br>'; } else { echo "catch Exception: " . $e->getCode() . ' ' . $e->getMessage() . '<br>'; } } set_exception_handler('_exception_handler'); // 注册异常处理方法来捕获异常 echo $foo['bar']; // 由于数组未定义,会产生一个notice级别的错误 trigger_error('人为触发一个错误', E_USER_ERROR); //人为触发错误 if (mt_rand(1, 10) > 5) { throw new Exception('This is a exception', 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
At this time we may be confused by PHP7 again. Which ones are processed by set_error_handler and which ones are processed by set_exception_handler. The manual does not clearly explain this. According to my summary, it generally will not cause the script to terminate. Errors will be handled by set_error_handler, and serious errors that will terminate the running of the script will be thrown as Errors, but not absolutely.
E_USER_ERROR artificially triggered above is an error that will interrupt the running of the script, but it will not It is not thrown as an Error exception, but is handled by the method registered by set_error_handler. This may be because this type of error is artificially generated by ourselves, so the error handling of PHP7 is still somewhat ambiguous, and it is not suitable for us to handle it ourselves. Be careful.
Recommended learning: php video tutorial
The above is the detailed content of How PHP7 uses set_error_handler and set_exception_handler to handle exception mechanisms. For more information, please follow other related articles on the PHP Chinese website!