PHP错误与异常关系梳理

作者: 乘风御上者 分类: PHP 发布时间: 2020-07-24 17:49

从PHP7开始改进了大多数错误,使其可以和异常一样被抛出,而后就可以使用try-catch进行捕获处理。不过还有一部分错误,作为漏网之鱼不能被捕获。怎么才能完美的解决问题呢?别急,容我慢慢道来。

先了解PHP执行时发生的几种错误级别:

Fatal Error:致命错误(脚本终止运行)

E_ERROR         // 致命的运行错误,错误无法恢复,暂停执行脚本
E_CORE_ERROR    // 在PHP初始化过程中由PHP引擎核心产生的致命错误
E_COMPILE_ERROR // 代码编译过程中由Zend脚本引擎产生的致命错误
E_USER_ERROR    // 用户自定义的致命错误(如:trigger_error('错误消息', E_USER_ERROR))
E_RECOVERABLE_ERROR// 发生了可被捕捉的致命错误

Parse Error:解析错误(脚本终止运行)

E_PARSE  //编译时的语法解析错误

Warning Error:警告错误(仅给出提示信息,脚本不终止运行)

E_WARNING         // 运行时警告
E_CORE_WARNING    // 在PHP初始化过程中由PHP引擎核心产生的警告
E_COMPILE_WARNING // 代码编译过程中由Zend脚本引擎产生的警告
E_DEPRECATED      // 运行代码若遇到在未来版本中可能无法正常工作的代码给出警告
E_USER_WARNING    // 用户自定义的警告
E_USER_DEPRECATED // 同样由用户自定义的警告

Notice Error:通知错误(仅给出通知信息,脚本不终止运行)

E_NOTICE      // 运行脚本遇到可能会表现为错误的情况时的通知
E_USER_NOTICE // 用户自定义的通知

还有两个特殊的错误:对上面所有级别的概括与补充

E_STRICT //	启用PHP对代码的修改建议,以确保代码具有最佳的互操作性和向前兼容性
E_ALL    //	包括以上所有(从PHP5.4开始)

当然我们可以自己定义发生哪种错误才会报告出来:

// 报告所有PHP错误,相当于error_reporting(E_ALL);
error_reporting(-1);

// 什么错误都不报告
error_reporting(0);

// 使用竖杠“|”表示只报告列出的这几种
error_reporting(E_ERROR | E_WARNING | E_PARSE | E_NOTICE);

// 报告所有错误,但排除E_NOTICE
error_reporting(E_ALL ^ E_NOTICE);

// 还可以在php.ini中配置
error_reporting=E_ALL

// 既然在php.ini中可以配置,那么也可以这样
ini_set('error_reporting', E_ALL);

设置完PHP的报错级别后,就要对不同的报告进行不同处理,当然我们要先捕捉到错误才行。

// 异常与错误的始祖
Throwable {
	abstract public getMessage ( void ) : string
	abstract public getCode ( void ) : int
	abstract public getFile ( void ) : string
	abstract public getLine ( void ) : int
	abstract public getTrace ( void ) : array
	abstract public getTraceAsString ( void ) : string
	abstract public getPrevious ( void ) : Throwable
	abstract public __toString ( void ) : string
}

Exception implements Throwable {
	// 使用final实现上述接口方法
}

Error implements Throwable {
	// 使用final实现上述接口方法
}

可以看出来,从PHP7开始增加了Throwable接口,异常类Exception与错误类Error都是实现自该接口,而现在大部分Error错误也可以通过try-catch捕捉到,如此就简单了:

try {
	// 业务逻辑
} catch (Throwable $e) {
	// 异常和错误都可以捕捉到
	// 真实场景一般不会这样简单粗暴的解决问题
}

虽然大多数错误都可以被捕获,但毕竟不是全部,仍然有一些致命错误(例如内存溢出)会像之前一样停止脚本执行。而且当抛出的异常没有被捕获时,同样是一个致命错误。此时还有几个函数可以上场补救:

set_exception_handler函数:自定义异常处理函数
当异常没有被catch捕获时,会尝试调用该函数自定义的函数。需要注意,当自定义函数执行完毕后,PHP脚本将停止运行。

set_error_handler函数:自定义错误处理函数
当发生错误时,会尝试调用该函数。若该函数存在则将所有错误都交给其所自定义的函数处理。不过该函数也不是万能的,有一些级别的错误:E_ERROR、E_PARSE、E_CORE_ERROR、E_CORE_WARNING、E_COMPILE_ERROR、E_COMPILE_WARNING不会被该函数捕获到,还有该函数所在的文件中产生的大多数E_STRICT错误,以及定义该函数之前的错误。

register_shutdown_function函数:脚本结束时触发的函数
该函数并不是错误处理函数,只是他的功能再搭配error_get_last函数能很好的处理一些错误。该函数会在脚本结束前作为最后一个被调用的函数,如脚本错误、异常、die、exit、正常结束都会调用该函数。

呼!费了好大劲才能将所有的错误处理掉,虽说PHP7已经有了想拨乱反正的趋势,但还是不够彻底。希望后面的版本中能将所有的异常及错误都概括到Throwable中吧。

如果觉得我的文章对您有用,请随意赞赏。您的支持将鼓励我继续创作!

发表回复