Laravel 的异常处理,像手套一样抓取。

v0.2.0 2023-06-20 20:04 UTC

This package is auto-updated.

Last update: 2024-09-30 01:38:11 UTC


README

使用 Laravel Glove 捕获异常。本包的主要目标是尽可能简化添加自定义错误页面和创建自定义错误处理器的过程,以便我们完成所需的功能。

这意味着

需求

Laravel Glove 为 Laravel 5.5 及更高版本编写,因此还要求 PHP 7.0 及更高版本。

安装

安装通过 composer 完成

composer require ellehamilton/glove

安装完成后,我们需要运行

php artisan vendor:publish

如果我们不使用自动发现,我们需要将 GloveServiceProvider 添加到 config/app.php 中的 providers 数组中

ElleTheDev\Glove\Providers\GloveServiceProvider::class,

Glove 自动与 Whoops 集成,无需额外配置。

错误页面

我们可以通过更新 config/glove-codes.php 来轻松自定义错误页面

基本示例

让我们将所有 404 状态码发送到我们的 errors.404 视图。

...

404 => [
    'view' => [
        'http' => 'errors.404',
        'ajax' => 'vendor.glove.ajax.exception'
    ]
]

...

带数据的错误页面

可以通过传递额外的数据到我们的视图来协助多次状态码的重用视图。

...

404 => [
    'view' => [
        'http' => 'errors.404',
        'ajax' => 'vendor.glove.ajax.exception'
    ],
    'data' => [
        'foo' => 'bar'
    ]
]

...

如果我们想让我们的视图在调试设置中显示为一个页面,我们可以将调试覆盖设置为 false,这样,例如,404 页面总是以这样的方式出现,而不是显示 Whoops 调试页面。

...

404 => [
    'view' => [
        'http' => 'errors.404',
        'ajax' => 'vendor.glove.ajax.exception'
    ],
    'debug' => false
]

...

debug 在不存在时默认为 true

通过更改 ajax 视图,我们可以使用我们自己的自定义 AJAX 格式。默认情况下,提供的视图将产生以下格式

{ error: { code: 404, message: "404 Page Not Found. The address you were looking for does not exist." } }

HTTP 状态码

我们可以在 config/glove.php 中指定哪个异常抛出哪个状态码

让我们让 MyException 抛出 403 状态码

'statusCodes' => [
    ...

    \App\Exceptions\MyException::class => 403,

    ...
]

状态码按顺序从上到下解释。第一个找到的抛出异常的异常实例将用作状态码。

例如,如果我们有以下内容

'statusCodes' => [
    \App\Exceptions\MyException::class => 403,
    \Exception::class => 500,
];

如果我们抛出 \App\Exceptions\MyException,状态码将是 403,因为它匹配并且是最先的。如果我们反转顺序

'statusCodes' => [
    \Exception::class => 500,
    \App\Exceptions\MyException::class => 403,
];

那么状态码将是 500,因为 \App\Exceptions\MyExceptionException 的实例,并且首先匹配。

\Symfony\Component\HttpKernel\Exception\HttpException 是一个特殊情况。当使用 abort(403) 或其变体时(不包括 404 状态码的情况),将产生包含状态码的 HttpException。Glove 会自动处理这种情况,并将 HttpException 解释为它包含的状态码,因此除非我们希望覆盖其处理,否则无需将其包含在状态码配置中。

日志记录

是否记录异常以及记录它们的日志级别,可以在config/glove.php中进行指定。

记录按照从上到下的顺序考虑,与状态码的处理方式相同。

跳过记录

我们可以通过将日志级别设置为ignore来忽略异常的记录。

'logLevels' => [
    ...

    \App\Exceptions\MyException::class => 'ignore',

    ...
]

更改日志级别

我们可以将日志级别从默认的'error'更改为Laravel的任何日志级别。

'logLevels' => [
    \App\Exceptions\MyException::class => 'critical'
]

自定义异常处理

编写自定义异常处理器的简单方法是实现\ElleTheDev\Glove\Contracts\Handler接口,然后在config/glove.php中指定何时运行。

只需实现一个函数。

public function handle(\Illuminate\Http\Request $request, \Exception $e);

自定义响应

要返回自定义响应,从handle方法中返回一个响应。

假设我们有一个自定义异常,MyException

namespace App\Exceptions;

class MyException extends \Exception
{
}

我们将编写一个自定义处理器来处理该异常。

namespace App\Exceptions\Handlers;

use ElleTheDev\Glove\Contracts\Handler;
use Illuminate\Http\Request;
use Exception;

class MyHandler implements Handler
{
    public function handle(Request $request, Exception $e)
    {
        return response(json_encode(['foo' => 'bar']))
            ->header('Content-Type', 'application/json');
    }
}

一旦MyHandler存在,我们就可以将其添加到config/glove.php中。

如果我们只想在它是AJAX请求时运行,我们可以将其添加到handlersajax部分。

'handlers' => [
    ...

    'ajax' => [
        ...

        \App\Exceptions\MyException::class => [
            \App\Exceptions\Handlers\MyHandler::class
        ],

        ...
    ]

    ...
],

异常可以具有多个处理器,就像返回的是null而不是响应对象一样,它将级联并继续处理处理器,直到接收到响应。

处理器按照从上到下的顺序解释,与状态码的处理方式相同。

无响应的自定义处理器

如果我们想让我们的处理器做些事情,但又想让其他处理器处理如何响应,我们可以简单地省略返回值或返回null以进行级联。

namespace App\Exceptions\Handlers;

use ElleTheDev\Glove\Contracts\Handler;

class MyHandler implements Handler
{
    public function handle(Request $request, Exception $e)
    {
        \Log::info("Something happened!");
    }
}