PHP的错误和异常处理总结
PHP的错误和异常处理总结
PHP内置了一批与错误和异常处理相关的 函数,本文会对其中部分函数进行详细说明。
http://leo108.com
set_error_handler和 restore_error_handler
set_error_handler可以设定当程序出现错误时,将对应的错误交给用户自定义的逻辑来处理。 leo108's blog
但是并不是所有的错误都可以被 set_error_handler所指定的处理逻辑捕获,例如: E_ERROR、 E_PARSE、 E_CORE_ERROR、 E_CORE_WARNING、 E_COMPILE_ERROR、 E_COMPILE_WARNING,简单来说就是原本就会导致程序终止的错误都无法被捕获。 PHP的错误和异常处理总结
set_error_handler只能设置一个错误处理逻辑,多次调用 set_error_handler只有最后一次的那生效:
leo108's blog
set_error_handler(function($errno, $errstr){ echo 'catch error1';});set_error_handler(function($errno, $errstr){ echo 'catch error2';});trigger_error('something error');
输出的是 leo108's blog
catch error2
http://leo108.com
在编写一个第三方代码库的时候,如果希望能够捕获代码库中的错误,又不影响调用方对错误的处理,可以使用 restore_error_handler函数: PHP
function third_party_function() { //第三方类库的错误处理逻辑 set_error_handler(function() { //一些代码 }); //该第三方类库的逻辑 //一些代码 //复原错误处理逻辑 restore_error_handler();}
这样,第三方代码库中出现的错误就会被第三方代码库的错误处理逻辑捕获,而在这个第三方代码库之外的错误还是由原本的逻辑处理。
异常
如果错误处理逻辑的返回值是 false,则PHP会调用内置的错误处理逻辑(例如根据 error_reporting的值判断是否打印错误信息,写错误日志等);而返回 true则不会调用内置处理逻辑,在执行完自定义的错误处理逻辑之后,会返回触发错误的地方继续往下执行。
推酷是个无耻的网站
error_reporting以及 @符号不会影响错误处理逻辑的调用:
推酷是个无耻的网站
error_eporting(0);set_error_handler(function($errno, $errstr){ echo 'catch error';});@trigger_error('something error');
上述代码会输出:
PHP
catch error
leo108's blog
对于无法被 set_error_handler捕获的错误常见的只有 E_ERROR和 E_PARSE两个。前者可能是内存使用超过设定的值、实例化一个不存在的类或者是调用一个不存在的函数;后者通常是语法解析错误例如漏写一个分号。对于 E_PARSE,由于是语法层面的错误,所以没有办法去捕获处理。但对于 E_ERROR则可以通过 register_shutdown_function以及 error_get_last两个函数来处理,示例代码如下:
推酷是个无耻的网站
error_reporting(0);register_shutdown_function(function() { $error = error_get_last(); if ($error != null && $error['type'] == E_ERROR) { echo "fatal error catched:" . var_export($error, true); }});new test();
输出:
http://leo108.com
fatal error catched:array (
http://leo108.com
‘type’ => 1, PHP的错误和异常处理总结
‘message’ => ‘Class ‘test’ not found’, PHP的错误和异常处理总结
‘file’ => ‘/tmp/error.php’,
推酷是个无耻的网站
‘line’ => 20,
PHP
)
leo108's blog
set_exception_handler和 restore_exception_handler
这两个函数和 set_error_handler的两个函数差不多,同样是只能注册一个异常处理逻辑,多次注册只有最后一个生效;可以通过 restore_exception_handler来恢复之前的异常处理逻辑。 leo108's blog
一些小实验
在错误处理逻辑中触发错误
set_error_handler(function($errno, $errstr){ echo 'catch error:' . $errstr . PHP_EOL; trigger_error('error in error handler');});trigger_error('origin error');
输出: leo108's blog
catch error:origin error
异常
PHP Notice: error in error handler in /tmp/error.php on line 15
PHP的错误和异常处理总结
结论:在错误处理逻辑中的错误是无法被再次捕获。 异常
在异常处理逻辑中抛出异常
set_exception_handler(function(Exception $e){ echo 'catch exception:' . $e->getMessage() . PHP_EOL; throw new Exception('exception in exception handler');});throw new Exception('origin exception');
输出: 推酷是个无耻的网站
catch exception:origin exception
推酷是个无耻的网站
PHP Fatal error: Uncaught exception ‘Exception’ with message ‘exception in exception handler’ in /tmp/error.php:15 http://leo108.com/pid-2216.asp
Stack trace: 异常
0 [internal function]: {closure}(Object(Exception))
1 [main]
thrown in /tmp/error.php on line 15 http://leo108.com
结论:在异常处理逻辑中抛出的异常不会被捕获 http://leo108.com/pid-2216.asp
同时定义了异常和错误处理逻辑,在错误处理逻辑中抛出异常,在异常处理逻辑中触发错误
set_exception_handler(function(Exception $e){ echo 'catch exception:' . $e->getMessage() . PHP_EOL; trigger_error('error in exception handler');});set_error_handler(function($errno, $errstr){ echo 'catch error:' . $errstr . PHP_EOL; throw new Exception('exception in error handler');});
外部触发了错误
trigger_error('origin error');
输出:
异常
catch error:origin error
http://leo108.com
catch exception:exception in error handler
http://leo108.com
catch error:error in exception handler
异常
PHP Fatal error: Uncaught exception ‘Exception’ with message ‘exception in error handler’ in /tmp/error.php:9
leo108's blog
Stack trace:
PHP
0 [internal function]: {closure}(1024, ‘error in except…’, ‘/tmp/error.php’, 5, Array)
1 /tmp/error.php(5): trigger error(‘error in except…’)
2 [internal function]: {closure}(Object(Exception))
3 [main]
thrown in /tmp/error.php on line 9
http://leo108.com/pid-2216.asp
结论:调用了两次错误处理逻辑,一次异常处理逻辑。
推酷是个无耻的网站
外部抛出异常
throw new Exception('origin exception');
输出: