Laravel 错误处理
简介
当启动一个新的Laravel项目时,框架就已经为我们配置好了错误和异常的处理。在App\Exceptions\Handler
类中,将记录由应用程序触发的所有异常,然后将其呈现给用户。在本文档中,我们将更深入地研究这个类。
配置
配置文件config/app.php
中的debug
选项确定向用户实际显示多少有关错误的信息。默认情况下,此选项设置为.env文件中的环境变量APP_DEBUG
的值。
对于本地开发,应将APP_DEBUG环境变量设置为true。在生产环境中,此值应设置为false。如果在生产环境中设置改置为true,有可能会将敏感的配置值暴露出去。
异常处理程序
Report 方法
所有异常均由App\Exceptions\Handler
类处理。此类包含两个方法:report
和render
。我们将详细研究每个方法。report
方法用于记录异常或将异常发送到Flare
,Bugsnag
或Sentry
之类的外部服务。默认情况下,report
方法将异常传递给了记录异常的基类。但是,我们可以使用我们自己的方式来报告异常。
例如,如果我们需要以不同的方式报告不同类型的异常,则可以使用PHP的instanceof比较运算符:
/**
* Report or log an exception.
*
* This is a great spot to send exceptions to Flare, Sentry, Bugsnag, etc.
*
* @param \Throwable $exception
* @return void
*/
public function report(Throwable $exception)
{
if ($exception instanceof CustomException) {
//
}
parent::report($exception);
}
与其使用
instanceof
在report方法中进行大量检查,不如考虑使用可报告的异常
全局日志上下文
如果可用,Laravel会自动将当前用户的ID作为上下文数据添加到每个异常的日志消息中。我们可以通过重写App\Exceptions\Handler
类的context
方法来定义自己的全局上下文数据。此信息将包含在我们的应用程序编写的每个异常的日志消息中:
/**
* Get the default context variables for logging.
*
* @return array
*/
protected function context()
{
return array_merge(parent::context(), [
'foo' => 'bar',
]);
}
report 哈数
有时我们可能需要报告异常,但继续处理当前请求。report函数允许我们使用异常处理程序的report的方法快速的报告一个异常,而无需渲染一个错误页面:
public function isValid($value)
{
try {
// Validate the value...
} catch (Throwable $e) {
report($e);
return false;
}
}
按类型忽略异常
异常处理程序的$dontReport
属性包含一个不会记录的异常类型数组。例如,由404错误以及其他几种类型的错误引起的异常不会写入日志文件。我们可以根据需要向此数组添加其他异常类型:
/**
* A list of the exception types that should not be reported.
*
* @var array
*/
protected $dontReport = [
\Illuminate\Auth\AuthenticationException::class,
\Illuminate\Auth\Access\AuthorizationException::class,
\Symfony\Component\HttpKernel\Exception\HttpException::class,
\Illuminate\Database\Eloquent\ModelNotFoundException::class,
\Illuminate\Validation\ValidationException::class,
];
Render 方法
render
方法负责将给定的异常转换为应发送回浏览器的HTTP响应。默认情况下,该异常将传递给基类,该基类将为我们生成相应的响应消息。但是,我们可以按照自己的方式检查异常类型或返回自己的自定义响应消息:
/**
* Render an exception into an HTTP response.
*
* @param \Illuminate\Http\Request $request
* @param \Throwable $exception
* @return \Illuminate\Http\Response
*/
public function render($request, Throwable $exception)
{
if ($exception instanceof CustomException) {
return response()->view('errors.custom', [], 500);
}
return parent::render($request, $exception);
}
可报告和可渲染的异常
与其在异常处理程序的report
和render
方法中检查异常的类型,不如我们直接在自定义异常类中直接定义report
和render
方法。这些方法存在时,框架将自动调用它们:
<?php
namespace App\Exceptions;
use Exception;
class RenderException extends Exception
{
/**
* Report the exception.
*
* @return void
*/
public function report()
{
//
}
/**
* Render the exception into an HTTP response.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\Response
*/
public function render($request)
{
return response(...);
}
}
我们可以使用类型限定指示report方法的任何必需依赖项,这些依赖项将由Laravel的服务容器自动注入到该方法中。
HTTP异常
某些异常描述了来自服务器的HTTP错误代码。例如,“找不到页面”错误(404),“未经授权的错误”(401),甚至是开发人员生成的500错误。为了从应用程序中的任何位置生成这样的响应,可以使用abort
帮助函数:
abort(404);
abort
将立即生成一个被异常处理程序渲染的异常。我们还可以提供响应文本:
abort(403, 'Unauthorized action.');
自定义HTTP错误页面
Laravel使显示各种HTTP状态代码的自定义错误页面变得简单。例如,如果我们希望为404 HTTP状态代码自定义错误页面,可以创建一个resources/views/errors/404.blade.php
。该文件将处理您的应用程序生成的所有404错误。该目录中的视图应被命名为与它们所对应的HTTP状态代码相匹配。abort
函数生成的HttpException
实例将作为$exception变量传递到视图:
<h2>{{ $exception->getMessage() }}</h2>
我们可以使用Artisan 命令vendor:publish
发布Laravel的错误页面模板。模板发布后,可以根据自己的喜好自定义它们:
$ php artisan vendor:publish --tag=laravel-errors