PHP7 错误异常处理

/*
 * 1 interface Throwable
2     |- Exception implements Throwable
3         |- ...
4     |- Error implements Throwable
5         |- TypeError extends Error
6         |- ParseError extends Error
7         |- ArithmeticError extends Error
8             |- DivisionByZeroError extends ArithmeticError
9         |- AssertionError extends Error
 * */

先列一下php有哪些关于错误异常警告相关设置和处理
1. 内部函数:error_reporting
2. ini配置:display_errors
3. ini配置: log_errors和error_log
4. set_exception_handler
5. set_error_handler
6. try/catch

1. error_reporting和display_errors,log_errors和error_log是针对于PHP标准错误处理机制(输出stderr,和error_log)所设置的,对set_exception_handler和set_error_handler没有机制没有影响
2. set_exception_handler 处理执行期间 用户期间 ERROR和EXCEPTION
3. set_error_handler 处理执行期间 内部期间 ERROR和EXCEPTION,WARNING,Undefined

直接讲各个场景的例子
在PHP7,ERROR级别跟EXCEPTION异常是一样的错误,所以这2个类型只讲一个

1. ERROR级别,有try catch捕获, 有set_exception_handler
error_reporting(E_ALL ^ E_NOTICE);
function exceptHandle($ex) {
    echo 'errorHandle' . $ex->getMessage().'\n';
}
set_exception_handler('exceptHandle');

try {
    $a = sdfsdf(); //没有定义的函数
} catch (Exception $e) { // 捕获用户自定义异常
    var_dump("Exception");
    var_dump($e);
} catch (Error $e) { //  捕获Error, TypeError,  ArithmeticError, DivisionByZeroError, AssertionError
    var_dump("Error");
    var_dump($e);
}

结论: 这个错误会被try cache捕获,不会进入到set_exception_handler处理,也不会被PHP标准错误处理

2. ERROR级别, 没有try catch捕获,有set_exception_handler
error_reporting(E_ALL ^ E_NOTICE);
function exceptHandle($ex) {
    echo 'errorHandle' . $ex->getMessage().'\n';
}
set_exception_handler('exceptHandle');

$a = sdfsdf(); //没有定义的函数

结论: 这个错误最后被set_exception_handler处理, 不会被PHP标准错误处理

3. ERROR级别, 没有try catch捕获,没有set_exception_handler
error_reporting(E_ALL ^ E_NOTICE);

$a = sdfsdf(); //没有定义的函数

结论: 由于这个ERROR级别错误,而且error_reporting只过滤NOTICE级别的错误,这个错误最后被PHP标准错误处理(stderr,error_log)

4. NOTICE级别, 有set_error_handler,返回true
error_reporting(E_ALL ^ E_NOTICE);
function errorHandle($errno, $errstr, $errfile, $errline) {
    echo 'errorHandle' . date('Y-m-d H:i:s') . $errno . $errstr . $errfile . $errline.'\n';
    return true;  // true 不传递给PHP标准错误处理
}
set_error_handler('errorHandle');

$a = [];
echo $a['asdf'].'\n'; // 访问没有index的数组下标


结论: 由于这个NOTICE级别错误,try catch不能捕获这个级别类的错误所以不用,这个错误最后被set_error_handler,
set_error_handler返回true, 所以不传递给PHP标准错误处理

5. NOTICE级别, 有set_error_handler,返回false
error_reporting(E_ALL ^ E_NOTICE);
function errorHandle($errno, $errstr, $errfile, $errline) {
    echo 'errorHandle' . date('Y-m-d H:i:s') . $errno . $errstr . $errfile . $errline.'\n';
    return false;  // false 传递给PHP标准错误处理
}
set_error_handler('errorHandle');
$a = [];
echo $a['asdf'].'\n'; // 访问没有index的数组下标


结论: 由于这个NOTICE级别错误,try catch不能捕获这个级别类的错误所以不用,这个错误最后被set_error_handler,
set_error_handler返回false, 同时传递给PHP标准错误处理处理,但是由于error_reporting过滤掉NOTICE,所以PHP标准错误处理直接返回不处理


6. NOTICE级别, 没有set_error_handler
error_reporting(E_ALL ^ E_NOTICE);

$a = [];
echo $a['asdf'].'\n'; // 访问没有index的数组下标


结论: 由于这个NOTICE级别错误,try catch不能捕获这个级别类的错误所以不用,最后被PHP标准错误处理处理,
但是由于error_reporting过滤掉NOTICE,所以PHP标准错误处理直接返回不处理

7. Warning级别, 有set_error_handler,返回true
error_reporting(E_ALL ^ E_NOTICE);
function errorHandle($errno, $errstr, $errfile, $errline) {
    echo 'errorHandle' . date('Y-m-d H:i:s') . $errno . $errstr . $errfile . $errline.'\n';
    return true;  // true 不传递给PHP标准错误处理
}
set_error_handler('errorHandle');

$B = SDFSDF; // Warning 访问没有定义的常量


结论: 由于这个Warning级别错误,try catch不能捕获这个级别类的错误所以不用,这个错误最后被set_error_handler,
set_error_handler返回true, 所以不传递给PHP标准错误处理

8. Warning级别, 有set_error_handler,返回false
error_reporting(E_ALL ^ E_NOTICE);
function errorHandle($errno, $errstr, $errfile, $errline) {
    echo 'errorHandle' . date('Y-m-d H:i:s') . $errno . $errstr . $errfile . $errline.'\n';
    return false;  // false 传递给PHP标准错误处理
}
set_error_handler('errorHandle');
$B = SDFSDF; // Warning 访问没有定义的常量


结论: 由于这个Warning级别错误,try catch不能捕获这个级别类的错误所以不用,这个错误最后被set_error_handler,
set_error_handler返回false, 同时传递给PHP标准错误处理处理,由于error_reporting过滤掉NOTICE,所以PHP标准错误处理会处理改错误


9. Warning级别, 没有set_error_handler
error_reporting(E_ALL ^ E_NOTICE);

$B = SDFSDF; // Warning 访问没有定义的常量


结论: 由于这个Warning级别错误,try catch不能捕获这个级别类的错误所以不用,最后被PHP标准错误处理处理,
由于error_reporting过滤掉NOTICE,所以PHP标准错误处理会处理改错误




//下面都是这篇文章的历史版本, 最终已上面为准




/*
 * 1.error_reporting(E_ALL ^ E_NOTICE)
 * 比如 error_reporting(E_ALL ^ E_NOTICE), 针对于E_NOTICE(未定义的变量或者没有对应下标的索引)错误,假如触发了这个错误
 * 如果用户自定义了set_error_handler,则被如果用户自定义了set_error_handler处理
 * 如果没有set_error_handler,那么就会交给PHP标准错误处理, 但是由于error_reporting(E_ALL ^ E_NOTICE) 排除了E_NOTICE的错误,
 * 所以php标准错误处理没有处理
 *
 * 2.error_reporting(E_ALL)
 * 比如 error_reporting(E_ALL), 针对于E_NOTICE(未定义的变量或者没有对应下标的索引)错误,假如触发了这个错误
 * 如果用户自定义了set_error_handler,则被如果用户自定义了set_error_handler处理
 * 如果没有set_error_handler,或者定义了set_error_handler但是错误函数返回了false的话,这2种情况会把 E_NOTICE 传递给PHP标准错误处理
 * 那么就会交给PHP标准错误处理, 由于error_reporting(E_ALL) 包含了E_NOTICE的等级错误,
 * 所以php标准错误处理会处理这个错误,根据display_errors = on 显示到标准输出上,
 * log_errors = on && error_log = path都定义的话,也会把这个E_NOTICE错误记录到对应的日志文件
 *
 * 3.总结
 * error_reporting 只是针对报告给php标准错误处理的错误等级设置
 * 而用户自定义处理try/catch和set_error_handler/set_exception_handler,可以捕获能捕获到的ERROR和Exception,跟error_reporting设置无关
 * error_reporting的设置只是用于处理已经越过用户自定义错误处理的那些错误(传递给php标准错误处理这里)才有效
 *
 * set_error_handler 如果捕获到错误,返回true 就不传递给php标准错误处理, 如果返回false的话 传递给php标准错误处理
 * set_exception_handler 捕获到的错误和异常, 不管返回true还是false,都不传递给php标准错误处理
 *
 * 手动try/catch优先级更高,没有手动捕获的,才会经过上面流程处理
 *
 */



// 如果用户没有手动try/cache ($Error || $Throwable) 捕获Error(为定义函数之类), TypeError(函数参数类型错误),  ArithmeticError, DivisionByZeroError, AssertionError的话 (运行时的错误),如果有注册set_exception_handler的话,就会被执行,否者如果有手动try/cache的话,就不会执行 set_exception_handler
// set_exception_handler 只是会类似钩子记录下日志,不会影响运行脚本的周期
// 这类错误要手动try/cache捕获, 不然会终止脚本运行,

// 如果用户没有手动try/cache ($Exception || $Throwable) 捕获Exception(throw new Exception("sdf"))的话 (用户抛出的逻辑异常的时候),如果有注册set_exception_handler的话,就会被执行,否则如果有手动try/cache的话,就不会执行 set_exception_handler
// set_exception_handler 只是会类似钩子记录下日志,不会影响运行脚本的周期
// 这类Exception错误要手动try/cache捕获, 不然会终止脚本运行,
set_exception_handler('exceptHandle');

// ParseError(编译语法解析时的错误) 语法错误是一种特殊的,在php脚本编译期间发生的错误,由于我们自定义错误和手动捕获, 都还没有执行,所以不走用户自定义错误处理,最后走php.ini的错误处理记录

function exceptHandle($ex) {
    var_dump("exceptHandle");
    var_dump(date('Y-m-d H:i:s') . $ex->getMessage() . PHP_EOL . $ex->getTraceAsString() . "\r\n");
}

// 捕获一些, Undefined index:, Undefined variable 的错误,这类错误不会被trycatch到,但可以被set_error_handler处理,不处理也不会终止脚本
set_error_handler('errorHandle');
 
// 总结: Undefined index:, Undefined variable 这类语法的错误,不会被trycatch到,但可以被set_error_handler处理,不处理也不会终止脚本
// 其他类型的错误,如果有try/catch优先被这个处理,否则如果有set_exception_handler则被这个处理, 再次之就是被默认php.ini处理
// 错误和异常如果不手动try/catch的话会被终止脚本

// ParseError 这类语法的错误,脚本都没编译好,更不可能执行,所以用户都处理不了,只有php内核处理
function errorHandle($errno, $errstr, $errfile, $errline) {
    var_dump("errorHandle");
    var_dump($errstr);
}
function sdfsdsdgsdf(array $sa)
{

}


try {
    $a = $b;
} catch (Exception $e) { // 捕获用户自定义异常
    var_dump("Exception");
    var_dump($e);
} catch (Error $e) { //  捕获Error, TypeError,  ArithmeticError, DivisionByZeroError, AssertionError
    var_dump("Error");
    var_dump($e);
}


exit();

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值