php 异常Exception和错误Error

一,Exception和Error的不同点:

1,产生方式不同

  • Exception是异常,只能由用户手动throw new Exception才能产生一个异常;
  • Error是错误,是程序报错所产生,也可以由用户调用 trigger_error()产生;

错误主要包含以下几种(按严重级别排序): Parse error > Fatal Error > Waning > Notice > Deprecated

2,捕获方式不同

  • Exception要通过 catch(Exception $e) 和 set_exception_handler 捕获;
  • Error要通过 catch(Error $e) 和 set_error_handler捕获,其中catch只能捕获Fatal
    Error,set_error_handler只能捕获Waning、Notice 和 Deprecated类型的错误。

在PHP7之后,set_exception_handler 不仅能捕获 Exception,也能捕获 Fatal Error类型(但是不能捕获notice和warning)。
因为PHP7之后,set_exception_handler的回调函数可以传入一个Throwable类的实例,而不仅限于Exception类的实例。

二,Exception和Error的相同点:

1,这两个类都继承自Throwable类,用 catch(Throwable $e) 可以同时捕获 Exception 和 Fatal Error类型的错误或异常。
2,Exception和Error具有相同的方法可以获得错误或异常信息:

getMessage();

getFile();

getLine();

三,异常捕获

  • catch(Exception $e) 只能捕获Exception,无法捕获Error;
  • catch(Error $e)只能捕获Fatal Error错误,不能捕获Warning、Notice、Deprecated错误,也不能捕获Exception;
  • catch(Throwable $e)可以捕获Fatal Error错误 和 Exception异常。
  • set_error_handler() 可以捕获Warning、Notice、Deprecated,不能捕获 Fatal Error和Parse error。
  • set_exception_handler()可以捕获Exception和Error。

被 set_error_handler()的自定义错误处理函数捕获到错误后,主逻辑仍可继续执行(因为Warning和Notice错误不足以终止程序)。

被 set_exception_handler() 的自定义错误处理函数捕获到错误或异常后,主逻辑不会继续往下执行。

如何让一个try catch 能够捕获所有的 Exception、Fatal Error、Warning、Notice、Parse错误?

思路:在 set_error_handler的回调函数中,将捕获到的Warning和Notice作为Exception抛出。再用 set_exception_handler 捕获异常。这么一来所有错误都能被当做异常捕获。

/**
 * 捕获Warning、Notice、Deprecated 错误
 */
function myErrorHandler($errno, $errStr, $errFile, $errLine)
{
    if (error_reporting() & $errno == 0) {
        return false;
    }
    $msg = "\"{$errStr}\" occured in File \"{$errFile}\" at Line {$errLine}\n";
    throw new Exception($msg, $errno);
}

/**
 * 捕获Exception和Error
 */
function myExceptionHandler(Throwable $e)
{
    if ($e instanceof Exception) {
        echo $e->getMessage();
        return;
    }
    echo "\"" . $e->getMessage() . "\" occured in File \"" . $e->getFile() . "\" at Line " . $e->getLine() . "\n";
}

/**
 * 错误兜底,无论程序是否报错,都会在结束时执行 myShutdownFunc()
 * 如果有错误未被myExceptionHandler或者myErrorHandler或者catch捕获,myShutdownFunc用来做错误兜底
 */
function myShutdownFunc()
{
    // 如果某个错误已经被 catch 或者 error_handler 或者 exception_handler 捕获,就不会再被 error_get_last()记录
    $err = error_get_last();
    if ($err && $err['type']) {
        myErrorHandler($err["type"], $err["message"], $err['file'], $err['line']);
    }
}


set_error_handler("myErrorHandler", E_ALL);
set_exception_handler("myExceptionHandler");
register_shutdown_function("myShutdownFunc");    // 注册一个 callback ,它会在脚本执行完成或者 exit() 后被调用。

try {
    // 1/0;    // Warning 先被 myErrorHandler 捕获,再被下方catch捕获,打印123
    // a;      // Notice 先被 myErrorHandler 捕获,再被下方catch捕获,打印123
    // a();    // Fatal Error 被 myExceptionHandler 捕获,不打印123
} catch (Exception $e) {
    var_dump($e);
}

echo 123;
exit;

最后还有一个问题没解决:如何捕获Parse Error语法错误?

实际上,php无法捕获语法错误,因为一个文件如果有语法错误,根本不会执行这个脚本里的任何代码就直接报错。

但可以通过 include/require 引入业务逻辑的php文件,如果 include(“test.php”) 的 test.php 有语法错误,则 include就会返回一个Fatal Error错误,Fatal Error错误就会被 myExceptionHandler() 捕获。

// ... 注册错误和异常的handler
try{
    include("test.php");	// test.php有语法错误,include会引发致命错误,此时会被 myExceptionHandler() 捕获,不打印123。
}catch(Exception $e){
    var_dump($e);
}
echo 123;
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值