E_ERROR 致命的运行时的致命错误,终止程序执行 E_CORE_ERROR PHP 启动时的致命错误 E_COMPILE_ERROR PHP编译时的致命错误 E_USER_ERROR 用户产生的致命错误
Parse Error 编译时的语法解析错误
E_WARNING 运行时警告 (非致命错误)。 E_CORE_WARNING PHP初始化启动过程当中发生的警告 (非致命错误) 。 E_COMPILE_WARNING 编译警告 E_USER_WARNING 用户产生的警告信息
E_NOTICE 运行时通知。表示脚本遇到可能会表现为错误的状况. E_USER_NOTICE 用户产生的通知信息。
set_error_handler($callback);//设置一个用户的函数(error_handler)来处理脚本中出现的错误。
如下级别的错误不能由用户定义的函数来处理:
E_ERROR、 E_PARSE、 E_CORE_ERROR、 E_CORE_WARNING、 E_COMPILE_ERROR、 E_COMPILE_WARNING,和在 调用 set_error_handler() 函数所在文件中产生的大多数 E_STRICT。php
也就是:set_error_handler($callback)只能捕获系统产生的一些Warning、Notice级别的Error。数组
<?php set_error_handler("error_handler"); function error_handler($errno,$errstr,$errfile,$errline){ $str=<<<EOF "errno":$errno "errstr":$errstr "errfile":$errfile "errline":$errline EOF; //获取到错误能够本身处理,好比记Log、报警等等 echo $str; } echo $test;//$test未定义,会报一个notice级别的错误
输出结果:闭包
"errno":8 "errstr":Undefined variable: test "errfile":/Users/shuchao/Desktop/handler.php "errline":13
获取PHP的fatal error,好比记录到Log里面,利于咱们分析线上问题,能够作线上服务的监控。函数
register_shutdown_function($callback)
register_shutdown_function(),就把你要注册进去的function放进【伪装是队列吧】,等到脚本正常退出或显示调用exit时,再把注册进去的function拉出来执行.ui
register_shutdown_function()调用的3种状况:spa
脚本正常退出时;code
在脚本运行(run-time not parse-time)出错退出时;队列
用户调用exit方法退出时。图片
error_get_last();//函数获取最后发生的错误。
该函数以数组的形式返回最后发生的错误。开发
返回的数组包含 4 个键和值:
[type] - 错误类型
[message] - 错误消息
[file] - 发生错误所在的文件
[line] - 发生错误所在的行
<?php register_shutdown_function( "fatal_handler" ); define('E_FATAL', E_ERROR | E_USER_ERROR | E_CORE_ERROR | E_COMPILE_ERROR | E_RECOVERABLE_ERROR| E_PARSE ); function fatal_handler() { if( $error = error_get_last()) { $errno = $error["type"]; $errfile = $error["file"]; $errline = $error["line"]; $errstr = $error["message"]; $str=<<<EOF "errno":$errno "errstr":$errstr "errfile":$errfile "errline":$errline EOF; //获取到错误能够本身处理,好比记Log、报警等等 echo $str; } }
在parse-time出错的时候,是不会调用register_shutdown_function()函数的。只有在run-time出错的时候,才会调用register_shutdown_function()。
下面咱们举例说明:
<?php register_shutdown_function("error_handler"); function error_handler(){ echo "Yeah,it's worked!"; } function test(){} function test(){}
执行结果以下:
Fatal error: Cannot redeclare test() (previously declared in /Users/shuchao/Desktop/error_handler.php:6) in /Users/shuchao/Desktop/error_handler.php on line 7
在执行error_handler.php的时候,因为重复定义了两个函数test(),在php的parse-time就出错了(不是run-time),因此不能回调register_shutdown_function()中的函数。
<?php register_shutdown_function("error_handler"); function error_handler(){ echo "Yeah,it's worked!"; } if(true){ function test(){} } function test(){}
执行结果以下:
Fatal error: Cannot redeclare test() (previously declared in /Users/shuchao/Desktop/error_handler.php:9) in /Users/shuchao/Desktop/error_handler.php on line 7 Yeah,it's worked!%
咱们看到,上面回调了register_shutdown_function().
由于咱们加了一个if()判断,if()里面的test()方法,至关于一个闭包,与外面的test()名称不冲突。
也就是,上面的代码在parse-time没有出错,而是在run-time的时候出错了,因此咱们可以获取到fatal error。
<?php register_shutdown_function("error_handler"); function error_handler(){ echo "Yeah,it's worked!"; }
<?php include './error_handler.php'; function test(){} function test(){}
执行 test_error.php的结果以下
Fatal error: Cannot redeclare test() (previously declared in /Users/shuchao/Desktop/test_error.php:3) in /Users/shuchao/Desktop/test_error.php on line 4
当咱们在运行test_error.php的时候,由于redeclare了两个test()方法,因此php的语法解析器在parse-time的时候就出错了。 因此不能回调register_shutdown_function()中的方法,不能catch住这个fatal error。
<?php register_shutdown_function("error_handler"); function error_handler(){ echo "Yeah,it's worked!"; }
<?php function test(){} function test(){}
require './error_handler.php'; require './test_error.php';
执行 include_all.php的结果以下
Fatal error: Cannot redeclare test() (previously declared in /Users/shuchao/Desktop/include_all.php:2) in /Users/shuchao/Desktop/include_all.php on line 3 Yeah,it's worked!%
上面咱们捕获了fatal_error.
由于在运行include_all.php的时候,include_all.php自己语法并无出错,也就是在parse-time的时候并无出错,而是include的文件出错了,也就是在run-time的时候出错了,这个时候是能回调register_shutdown_function()中的函数的。
<?php register_shutdown_function( "fatal_handler" ); set_error_handler("error_handler"); define('E_FATAL', E_ERROR | E_USER_ERROR | E_CORE_ERROR | E_COMPILE_ERROR | E_RECOVERABLE_ERROR| E_PARSE ); //获取fatal error function fatal_handler() { $error = error_get_last(); if($error && ($error["type"]===($error["type"] & E_FATAL))) { $errno = $error["type"]; $errfile = $error["file"]; $errline = $error["line"]; $errstr = $error["message"]; error_handler($errno,$errstr,$errfile,$errline); } } //获取全部的error function error_handler($errno,$errstr,$errfile,$errline){ $str=<<<EOF "errno":$errno "errstr":$errstr "errfile":$errfile "errline":$errline EOF; //获取到错误能够本身处理,好比记Log、报警等等 echo $str; }
当异常抛出的时候,咱们是想要去捕获他,并去作处理的。
因此异常常常被当作程序的控制流程使用。
Error是不可恢复的,是在开发过程当中要去解决的。
我想执行insert语句插入一条数据,可能插入失败(好比ID重复),注意是可能失败,因此这是一个可能的状况,也就是异常状况。
咱们就能够使用异常来处理这个问题
try { $row->insert(); $inserted = true; } catch (Exception $e) { echo "There was an error inserting the row - ".$e->getMessage(); $inserted = false; } echo "Some more stuff";
假设程序中的有些地方直接throw了异常,没有进行catch。
咱们如今想要无论在程序的任何一个地方throw异常,即使在throw的地方没有被catch,咱们也要能catch住,如何作到呢?
//设置默认的异常处理程序,用于没有用 try/catch 块来捕获的异常。 在 exception_handler 调用后异常会停止。 set_exception_handler()
<?php set_exception_handler("my_exception"); function my_exception($exception){ echo $exception->getMessage(); }
<?php require "./exception_handler.php"; throw new Exception("I am Exception");
如今咱们运行 test_exception.php,结果以下:
I am Exception //证实咱们throw的Exception被捕获了
更多精彩,请关注公众号“聊聊代码”,让咱们一块儿聊聊“左手代码右手诗”的事儿。