Laravel Exception处理逻辑解析

vendor/laravel/framework/src/Illuminate/Foundation/Application.php

  1. app首先继承了container,作为一个容器类存在
  2. 注册了laravel运行过程的需要的基础类进容器,并且生成了运行需要的实例。承担了初始化功能。这里需要额外说一下,app里面说的所谓注册,不是指绑定,应该是直接直接实例化了,并注入到容器。但是,针对provider,实例化了provider,并运行了,并不会生成实际的类,而是将类绑定。

ExceptionHandler的注册就是在Application的__construct方法中。

$this->registerErrorHandling();

接着我们来到定义该方法的trait:RegistersExceptionHandlers找到该方法。看一下该方法实现了什么样的逻辑。便于理解我加上了一些注释。

protected function registerErrorHandling()
{
error_reporting(-1);//-1报告所有异常,包括后续新定义的异常级别,作用与E_ALL相同 /** set_error_handler,set_exception_handler,register_shutdown_function分别注册不同级别不同类型异常的处理方法。 */ set_error_handler(function ($level, $message, $file = '', $line = 0) {
if (error_reporting() & $level) {
throw new ErrorException($message, 0, $level, $file, $line);
}
});//代替标准错误处理方法 set_exception_handler(function ($e) {
$this->handleUncaughtException($e);
});//兜底异常处理方法注册 register_shutdown_function(function () {
$this->handleShutdown();
});//注册一个在脚本正常或非正常情况终止执行时调用的方法。(终极兜底)
}

我们看到laravel主要通过三个原生方法来实现主要的ExceptionHandler机制。下面我们分开看一下这里都分别注册了哪些函数。

set_error_handler

function ($level, $message, $file = '', $line = 0) {
if (error_reporting() & $level) {
throw new ErrorException($message, 0, $level, $file, $line);
}
}

这块很简单,set_error_handler注册的函数会代替原生的报错处理逻辑。这里可以看到laravel将执行error作为异常抛出。并且保留了error的主要信息。(level,msg,file,line)

set_exception_handler

/**set_exception_handler(function ($e) {
$this->handleUncaughtException($e);
});**/ protected function handleUncaughtException($e)
{
//从容器中实例化一个真正的handler。(使用make方法)
$handler = $this->resolveExceptionHandler();
//如果获取到的是Error,通过Error信息实例化一个已定义的“可抛出的致命错误”
if ($e instanceof Error) {
$e = new FatalThrowableError($e);
}
//记录日志(先判断是否报告)
$handler->report($e);
//render错误
if ($this->runningInConsole()) {
$handler->renderForConsole(new ConsoleOutput, $e);
} else {
$handler->render($this->make('request'), $e)->send();
}
}
  1. resolveExceptionHandler方法从容器中make了一个handler实例,从该方法可以找到laravel实现的handler方法。该方法会判断是否绑定抽象类型来判断使用开发者自行绑定的ExceptionHandler还是系统自带的。handler的作用只有一点,就是解析异常,并将异常处理成我们想要的,更加用户友好的方式展示。(++render方法,可以看“Laravel\Lumen\Exceptions\Handler”,该类实现了Laravel的ExceptionHandler接口,想要自定义异常输出的话也可以参考该类++)
  2. report和render方法都是handler中定义的,report会先进行判断,并根据判断结果决定是否记录log。render自然不必多说,formatexception info,并作为一个HTTP response输出。

register_shutdown_function

protected function handleShutdown()
{
if (! is_null($error = error_get_last()) && $this->isFatalError($error['type'])) {
$this->handleUncaughtException(new FatalErrorException(
$error['message'], $error['type'], 0, $error['file'], $error['line']
));
}
}

error_get_last()是5.2版本实现的方法,能够很好的配合的register_shutdown_function进行兜底处理。改善了需要自定义变量判断的方法。

error_get_last 返回了一个关联数组,描述了最后错误的信息,以该错误的 "type"、 "message"、"file" 和 "line" 为数组的键。

另外,该方法规定只有致命的错误才会启动。

最新文章

  1. PowerBuilder反编译
  2. spring aop配置及用例说明(4)
  3. 浅谈string
  4. Maven Build Life Cycle--reference
  5. [连载]JavaScript讲义(02)--- JavaScript核心编程
  6. ZEN_CART_如何添加自定义页面
  7. flowable设计器插件安装
  8. JAVA 列表输入学生的信息
  9. python安装小结
  10. 展示博客---Alpha版本展示
  11. 【译】第5节---Code First约定
  12. SqlServer添加触发器不让删除数据
  13. 关于bfs与dfs的标记区别
  14. nginx配置详解(转)
  15. 为exchange 2010 owa 添加验证码
  16. java 反射 报错:Attempt to get java.lang.Integer field "..." with illegal data type conversion to int
  17. [转] 基于C#的波形显示控件的实现
  18. javascript之input字符串不为空
  19. HDU 5316——Magician——————【线段树区间合并区间最值】
  20. Linux文件扩展名

热门文章

  1. GUI练习3
  2. Spark机器学习中ml和mllib中矩阵、向量
  3. maven中的mirrors
  4. python函数查询、数学和比较操作符、二元操作符
  5. Photoshop 基础三 制作简单按钮
  6. Android Studio在华为真机上运行无法输出Debug日志解决
  7. Luogu4156 WC2016 论战捆竹竿 KMP、同余类最短路、背包、单调队列
  8. Luogu4131 WC2005 友好的生物 状压DP
  9. LOJ2537 PKUWC2018 Minimax 树形DP、线段树合并
  10. (转)PostgreSQL pg_dump&psql 数据的备份与恢复