Laravel Exception处理逻辑解析
Laravel Exception处理逻辑解析
vendor/laravel/framework/src/Illuminate/Foundation/Application.php
- app首先继承了container,作为一个容器类存在
- 注册了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();
}
}
- resolveExceptionHandler方法从容器中make了一个handler实例,从该方法可以找到laravel实现的handler方法。该方法会判断是否绑定抽象类型来判断使用开发者自行绑定的ExceptionHandler还是系统自带的。handler的作用只有一点,就是解析异常,并将异常处理成我们想要的,更加用户友好的方式展示。(++render方法,可以看“Laravel\Lumen\Exceptions\Handler”,该类实现了Laravel的ExceptionHandler接口,想要自定义异常输出的话也可以参考该类++)
- 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" 为数组的键。
另外,该方法规定只有致命的错误才会启动。
Laravel Exception处理逻辑解析的更多相关文章
- Laravel Exception结合自定义Log服务的使用
Laravel Exception结合自定义Log服务的使用 第一部分:laravel关于错误和异常的部分源码 第二部分:自定义异常的使用(结合serviceprovider monolog elas ...
- ZooKeeper(二):多个端口监听的建立逻辑解析
ZooKeeper 作为优秀的分布系统协调组件,值得一探究竟.它的启动类主要为: 1. 单机版的zk 使用 ZooKeeperServerMain 2. 集群版的zk 使用 QuorumPeerMai ...
- Hystrix失败处理逻辑解析
在上篇文章Hystrix工作流程解析中,我们整体介绍了Hystrix的工作流程,知道了Hystrix会在下面四种情况下发生降级: 熔断器打开 线程池/信号量跑满 调用超时 调用失败 本篇文章则介绍一下 ...
- laravel启动过程简单解析
:first-child{margin-top:0!important}img.plugin{box-shadow:0 1px 3px rgba(0,0,0,.1);border-radius:3px ...
- Spring 声明事务中transactionAttributes属性 + - Exception 实现逻辑
下面是一段典型的Spring 声明事务的配置: <bean id=“baseTxProxy” lazy-init=“true”class=“org.springframework.transac ...
- laravel的启动过程解析
laravel的启动过程,也是laravel的核心,对这个过程有一个了解,有助于得心应手的使用框架,希望能对大家有点帮助. 统一入口 laravel框架使用了统一入口,入口文件:/public/ind ...
- ZooKeeper(五):事务处理之更新数据逻辑解析
通过前些文章,我们已经完全从整体架构和数据接入方面理解了ZK的前情工作.接下来,我们就来看ZK的正式工作吧. 本文以 setData /a data 这个命令作为出发点,来观察zk是如何处理来自客户端 ...
- 随便聊聊 SOA & SOAP & WebService 的一些东西,以及客户端开发的代码逻辑解析
http://blog.csdn.net/hikaliv/article/details/6459779 一天的时间调通了一个 WebService 的 Java 端的 C/S.一个 Android ...
- LARAVEL IOC容器 示例解析
<?php class People { public $dog = null; public function __construct() { $this->dog = new Dog( ...
随机推荐
- 控件_CheckBox(多选按钮)
import android.os.Bundle; import android.app.Activity; import android.widget.CheckBox; import androi ...
- DStream算子讲解(一)
先把目录列好,方便有条理的进行整理
- 最简单例子图解JVM内存分配和回收(转)
本文转自http://ifeve.com/a-simple-example-demo-jvm-allocation-and-gc/ http://www.idouba.net/a-simple-exa ...
- Qt+QGIS二次开发:向shp矢量图层中添加新的字段
添加一个新的字段到shp文件中,并且从Excel里导入数据到该字段.原shp文件里的字段ID应该与Excel里的字段ID一一对应才能正确的导入.下图分别是shp的字段和Excel的字段 将class字 ...
- MATLAB——LMS算法(△规则Delta Rule)
- 一个网工的Linux学习过程
机缘巧合下,在快要毕业时找到了一份网络工程师的工作,对于学习通信工程的我来说,也不算是跨专业就业吧.在入职之前也了解了一下网络工程师的学习路径,网络工程师是从事计算机信息系统的设计.建设.运行和维护工 ...
- PAT A1074 Reversing Linked List (25 分)——链表,vector,stl里的reverse
Given a constant K and a singly linked list L, you are supposed to reverse the links of every K elem ...
- C# 语法四 修饰符
1.sealed 不能派生 2.internal 仅仅在本项目中被访问 3.public 整个系统 4.private 本类访问 5.protected 本类.派生类访问 using System; ...
- Linux命令——head/tail
一.head head主要是用来显示档案的开头至标准输出中,默认打印相应文件的开头10 行. 1)命令格式 head [参数] [文件] 2)常用参数 -q 隐藏文件名-v 显示文件名 ...
- Javascript数组Array的forEach方法
Javascript数组Array的forEach扩展方法 forEach是最常用到的数组扩展方法之一,相当于参数化循环数组,它简单的在数组的每一个元素上应用传入的函数,这也意味着只有存在的元素会被访 ...