Laravel核心解读之异常处理的实践过程

前言

异常处理是编程中十分重要但也最容易被人忽视的语言特性,它为开发者提供了处理程序运行时错误的机制,对于程序设计来说正确的异常处理能够防止泄露程序自身细节给用户,给开发者提供完整的错误回溯堆栈,同时也能提高程序的健壮性。

这篇文章我们来简单梳理一下Laravel中提供的异常处理能力,然后讲一些在开发中使用异常处理的实践,如何使用自定义异常、如何扩展Laravel的异常处理能力。

下面话不多说了,来一起看看详细的介绍吧

注册异常Handler

这里又要回到我们说过很多次的Kernel处理请求前的bootstrap阶段,在bootstrap阶段的Illuminate\Foundation\Bootstrap\HandleExceptions 部分中Laravel设置了系统异常处理行为并注册了全局的异常处理器:

class HandleExceptions
{
 public function bootstrap(Application $app)
 {
  $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');
  }
 }
 
 
 public function handleError($level, $message, $file = '', $line = 0, $context = [])
 {
  if (error_reporting() & $level) {
   throw new ErrorException($message, 0, $level, $file, $line);
  }
 }
}

set_exception_handler([$this, 'handleException'])将HandleExceptions的handleException方法注册为程序的全局处理器方法:

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

 $this->getExceptionHandler()->report($e);

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

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

// 渲染CLI请求的异常响应
protected function renderForConsole(Exception $e)
{
 $this->getExceptionHandler()->renderForConsole(new ConsoleOutput, $e);
}

// 渲染HTTP请求的异常响应
protected function renderHttpResponse(Exception $e)
{
 $this->getExceptionHandler()->render($this->app['request'], $e)->send();
}

在处理器里主要通过ExceptionHandler的report方法上报异常、这里是记录异常到storage/laravel.log文件中,然后根据请求类型渲染异常的响应生成输出给到客户端。这里的ExceptionHandler就是\App\Exceptions\Handler类的实例,它是在项目最开始注册到服务容器中的:

// bootstrap/app.php

/*
|--------------------------------------------------------------------------
| Create The Application
|--------------------------------------------------------------------------
*/

$app = new Illuminate\Foundation\Application(
 realpath(__DIR__.'/../')
);

/*
|--------------------------------------------------------------------------
| Bind Important Interfaces
|--------------------------------------------------------------------------
*/
......

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

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:http://www.heiqu.com/6047.html