【laravel 实现杂谈】异常的处理 - (sunznx) 振翅飞翔
04 September 2019

bootstrap

Illuminate/Foundation/Bootstrap/HandleExceptions.php

public function bootstrap(Application $app)
{
    self::$reservedMemory = str_repeat('x', 10240);

    $this->app = $app;

    error_reporting(-1);

    set_error_handler([$this, 'handleError']);

    set_exception_handler([$this, 'handleException']);

    register_shutdown_function([$this, 'handleShutdown']);

    if (! $app->environment('testing')) {
        ini_set('display_errors', 'Off');
    }
}

要正常捕捉 php 的 错误/异常,需要注册 set_error_handler, set_exception_handler, register_shutdown_function

对 Error 的处理

handleError 通过 ErrorException,将 Error 转换成 Exception

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

对 shutdown 的处理

handleShutdown 的处理逻辑和 handleError 类似,通过 error_get_last 拿到 error 再转换成 Exception

public function handleShutdown()
{
    if (! is_null($error = error_get_last()) && $this->isFatal($error['type'])) {
        $this->handleException($this->fatalExceptionFromError($error, 0));
    }
}

对 Exception 的处理

handleException 的主要逻辑是调用 getExceptionHandler()reportrender 方法

public function handleException($e)
{
    if (! $e instanceof Exception) {
        $e = new FatalThrowableError($e);
    }

    try {
        self::$reservedMemory = null;

        $this->getExceptionHandler()->report($e);
    } catch (Exception $e) {
        //
    }

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

protected function renderHttpResponse(Exception $e)
{
    $this->getExceptionHandler()->render($this->app['request'], $e)->send();
}

getExceptionHandler

protected function getExceptionHandler()
{
    return $this->app->make(ExceptionHandler::class);
}

ExceptionHandler::class 在启动的时候绑定。bootstrap/app.php

$app->singleton(
    Illuminate\Contracts\Debug\ExceptionHandler::class,
    App\Exceptions\Handler::class
);