文档章节

Laravel源码入门-启动引导过程(八)HandleExceptions

zhmsong
 zhmsong
发布于 2017/05/18 22:35
字数 940
阅读 38
收藏 0

上文介绍了 LoadConfiguration,载入 config/*.php 配置,在 《Laravel源码入门-启动引导过程(五)$kernel->handle($request)》中第三个要载入的是 HandleExceptions,也就是 Foundation\Http\Kernel::bootstrapers[] 的第三个

\Illuminate\Foundation\Bootstrap\HandleExceptions::class, 如下:

// Illuminate\Foundation\Http\Kernel.php 片段

   /**
     * The bootstrap classes for the application.
     * 引导类,起引导作用的类
     *
     * @var array
     */
    protected $bootstrappers = [
        // 载入服务器环境变量(.env 文件)
        \Illuminate\Foundation\Bootstrap\LoadEnvironmentVariables::class,
        // 载入配置信息(config 目录)
        \Illuminate\Foundation\Bootstrap\LoadConfiguration::class,
        // 配置如何处理异常
        \Illuminate\Foundation\Bootstrap\HandleExceptions::class,
        // 注册 Facades
        \Illuminate\Foundation\Bootstrap\RegisterFacades::class,
        // 注册 Providers
        \Illuminate\Foundation\Bootstrap\RegisterProviders::class,
        // 启动 Providers
        \Illuminate\Foundation\Bootstrap\BootProviders::class,
    ];

我们再直接贴出 HandleExceptions 类的代码,进行分析,非常直观,如下:

<?php  

namespace Illuminate\Foundation\Bootstrap;

use Exception;
use ErrorException;
use Illuminate\Contracts\Debug\ExceptionHandler;
use Illuminate\Contracts\Foundation\Application;
use Symfony\Component\Console\Output\ConsoleOutput;
use Symfony\Component\Debug\Exception\FatalErrorException;
use Symfony\Component\Debug\Exception\FatalThrowableError;

class HandleExceptions
{
    /**
     * The application instance.
     *
     * @var \Illuminate\Contracts\Foundation\Application
     */
    protected $app;

    /**
     * Bootstrap the given application.
     * 引导给定(注入)的 $app。
     *
     * @param  \Illuminate\Contracts\Foundation\Application  $app
     * @return void
     */
    public function bootstrap(Application $app)
    {
        $this->app = $app;

        // 报告所有 PHP 错误,和 error_reporting(E_ALL); 一样
        // ini_set('error_reporting', E_ALL);
        // 参考:http://php.net/manual/zh/errorfunc.constants.php
        error_reporting(-1);

        // 设置自定义的错误处理方法,数组形式表示 类和类的函数
        set_error_handler([$this, 'handleError']);

        // 设置自定义的异常处理方法
        set_exception_handler([$this, 'handleException']);

        // 注册PHP中止时自定义的处理方法(为什么是 register_ 而不是 set_?)
        register_shutdown_function([$this, 'handleShutdown']);

        // 如何应用环境是 .env 文件中 APP_ENV=testing,则关闭错误显示
        // 但是,尽管 display_errors 也可以在运行时设置 (使用 ini_set()), 
        // 但是脚本出现致命错误时任何运行时的设置都是无效的。 
        // 因为在这种情况下预期运行的操作不会被执行
        // 参见:http://php.net/manual/zh/errorfunc.configuration.php#ini.display-errors
        // 这里 environment() 带了参数,据说 php 弱类型,不定义参数也可以传入,
        // 使用 func_get_arg() 和 func_get_args() 获取,见 $app->environment()源码和php说明。
        if (! $app->environment('testing')) {
            ini_set('display_errors', 'Off');
        }
    }

    /**
     * Convert PHP errors to ErrorException instances.
     * 转换 php 错误 为 ErrorException实例(php内置类)
     *
     * handleError() 是按照PHP中set_error_handler(callable $error_handler )中
     * $error_handler 严格定义的,参见 set_error_handler 文档,最终由 trigger_error()触发。
     *
     * @param  int  $level
     * @param  string  $message
     * @param  string  $file
     * @param  int  $line
     * @param  array  $context
     * @return void
     *
     * @throws \ErrorException
     */
    public function handleError($level, $message, $file = '', $line = 0, $context = [])
    {
        if (error_reporting() & $level) {
            throw new ErrorException($message, 0, $level, $file, $line);
        }
    }

    /**
     * Handle an uncaught exception from the application.
     * 处理程序本身代码未能想到(处理,写代码时想不到的)的异常
     *
     * Note: Most exceptions can be handled via the try / catch block in
     * the HTTP and Console kernels. But, fatal error exceptions must
     * be handled differently since they are not normal exceptions.
     *
     * 大多数能用 try/catch 捕获到,但是但凡捕获不到的,都作为 Fatal?
     *
     * @param  \Throwable  $e
     * @return void
     */
    public function handleException($e)
    {
        // 记住 instanceof 是运算符,不是函数
        if (! $e instanceof Exception) {
            $e = new FatalThrowableError($e);
        }

        // 实例化异常处理对象来报告 $e。
        $this->getExceptionHandler()->report($e);

        if ($this->app->runningInConsole()) {
            $this->renderForConsole($e);
        } else {
            $this->renderHttpResponse($e);
        }
    }

    /**
     * Render an exception to the console.
     * 异常渲染到 console
     *
     * @param  \Exception  $e
     * @return void
     */
    protected function renderForConsole(Exception $e)
    {
        $this->getExceptionHandler()->renderForConsole(new ConsoleOutput, $e);
    }

    /**
     * Render an exception as an HTTP response and send it.
     * 异常渲染到HTTP response,并 send().
     *
     * @param  \Exception  $e
     * @return void
     */
    protected function renderHttpResponse(Exception $e)
    {
        $this->getExceptionHandler()->render($this->app['request'], $e)->send();
    }

    /**
     * Handle the PHP shutdown event.
     *
     * @return void
     */
    public function handleShutdown()
    {
        // $error 由 error_get_last() 返回和定义,
        // 有固定的 "type"、 "message"、"file" 和 "line" 键值。
        if (! is_null($error = error_get_last()) && $this->isFatal($error['type'])) {
            $this->handleException($this->fatalExceptionFromError($error, 0));
        }
    }

    /**
     * Create a new fatal exception instance from an error array.
     *
     * @param  array  $error
     * @param  int|null  $traceOffset
     * @return \Symfony\Component\Debug\Exception\FatalErrorException
     */
    protected function fatalExceptionFromError(array $error, $traceOffset = null)
    {
        return new FatalErrorException(
            $error['message'], $error['type'], 0, $error['file'], $error['line'], $traceOffset
        );
    }

    /**
     * Determine if the error type is fatal.
     *
     * @param  int  $type
     * @return bool
     */
    protected function isFatal($type)
    {
        return in_array($type, [E_COMPILE_ERROR, E_CORE_ERROR, E_ERROR, E_PARSE]);
    }

    /**
     * Get an instance of the exception handler.
     *
     * @return \Illuminate\Contracts\Debug\ExceptionHandler
     */
    protected function getExceptionHandler()
    {
        return $this->app->make(ExceptionHandler::class);
    }
}

至此所有的错误处理、异常处理、PHP中止处理的准备工作都已配置完成。

 

 

© 著作权归作者所有

共有 人打赏支持
zhmsong
粉丝 40
博文 126
码字总数 65130
作品 0
海淀
程序员
Laravel5.3之bootstrap源码解析

说明:Laravel在把Request通过送入中间件Middleware和路由Router之前,还做了程序的启动Bootstrap工作,本文主要学习相关源码,看看Laravel启动程序做了哪些具体工作,并将个人的研究心得分享...

botkenni
2016/10/28
363
0
Laravel5.3之Session源码解析(中)

说明:在上篇中学习了session的启动过程,主要分为两步,一是session的实例化,即IlluminateSessionStore的实例化;二是从session存储介质redis中读取的数据。Laravel5.3把session垃圾回收放...

botkenni
2016/11/19
12
0
Laravel5.3之Session源码解析(下)

说明:在中篇中学习了session的CRUD增删改查操作,本篇主要学习关闭session的相关源码。实际上,在Laravel5.3中关闭session主要包括两个过程:保存当前URL到session介质中;在Response Head...

botkenni
2016/11/19
56
0
Laravel 5.1 源码阅读

安装,和创建项目,都是通过Composer,简单,略过。 Entry && Kernel 网站入口文件,${Laravel-project}/public/index.PHP: 生成Request,处理Request(),生成Response,发送Resonse。常规...

botkenni
2016/10/09
25
0
Laravel5.2之Redis保存页面浏览量

说明:本文主要讲述使用Redis作为缓存加快页面访问速度。同时,会将开发过程中的一些截图和代码黏上去,提高阅读效率。 备注:最近在学习github上别人的源码时,发现好多在计算一篇博客页面访...

botkenni
2016/10/21
16
0

没有更多内容

加载失败,请刷新页面

加载更多

WinDbg

参考来自:http://www.cnit.net.cn/?id=225 SRV*C:\Symbols*http://msdl.microsoft.com/download/symbols ctrl + d to open dump_file Microsoft (R) Windows Debugger Version 6.12.0002.633......

xueyuse0012
今天
2
0
OSChina 周五乱弹 —— 想不想把92年的萝莉退货

Osc乱弹歌单(2018)请戳(这里) 【今日歌曲】 @罗马的王:分享松澤由美的单曲《地球ぎ》 很久没看圣斗士星矢了 《地球ぎ》- 松澤由美 手机党少年们想听歌,请使劲儿戳(这里) @开源中国首...

小小编辑
今天
13
1
springBoot条件配置

本篇介绍下,如何通过springboot的条件配置,控制Bean的创建 介绍下开发环境 JDK版本1.8 springboot版本是1.5.2 开发工具为 intellij idea(2018.2) 开发环境为 15款MacBook Pro 前言 很多时候,...

贺小五
今天
1
0
javascript source map 的使用

之前发现VS.NET会为压缩的js文添加一个与文件名同名的.map文件,一直没有搞懂他是用来做什么的,直接删除掉运行时浏览器又会报错,后来google了一直才真正搞懂了这个小小的map文件背后的巨大...

粒子数反转
昨天
1
0
谈谈如何学Linux和它在如今社会的影响

昨天,还在农耕脑力社会,今天已经人工智能技术、大数据、信息技术的科技社会了,高速开展并迅速浸透到当今科技社会的各个方面,Linux日益成为人们信息时代的到来,更加考验我们对信息的处理程...

linux-tao
昨天
1
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部