侯体宗的博客
  • 首页
  • Hyperf版
  • beego仿版
  • 人生(杂谈)
  • 技术
  • 关于我
  • 更多分类
    • 文件下载
    • 文字修仙
    • 中国象棋ai
    • 群聊
    • 九宫格抽奖
    • 拼图
    • 消消乐
    • 相册

在Laravel项目中Exception(异常处理)优化最佳实践方式浅析

Laravel  /  管理员 发布于 1年前   1113

在开发 Web 应用程序时,异常处理是至关重要的,当应用程序发生异常时,我们希望能够及时捕获和处理异常,并提供有用的错误信息给用户或开发团队。

下面看看在Laravel中如何实现全局异常处理,并探讨一些最佳实践,包括日志记录、异常监控和报警以及单元测试。

在 Laravel 框架中,我们可以通过全局异常处理来统一处理应用程序中的异常情况。

本文将介绍如何在 Laravel 中实现全局异常处理,并分享一些最佳实践。


实现步骤

1. 创建自定义异常处理器类:

创建一个自定义的异常处理器类,用于处理应用程序中的异常。

可以在 app/Exceptions 目录下创建一个新的异常处理器类,

例如 CustomExceptionHandler.php。

<?php
namespace App\Exceptions;
use Exception;
use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
class CustomExceptionHandler extends ExceptionHandler
{
  // 自定义数据
  protected $data;
    public function __construct($message, $code, $data = null)
    {
        parent::__construct($message, $code);
        $this->data = $data;
    }
  
    public function render($request, Exception $exception)
    {
        // 自定义异常处理逻辑
        // ...
      // 在这里可以将自定义数据记录到日志或其他地方
        // 可以使用 $this->data 访问自定义数据
        return parent::render($request, $exception);
    }
}


2. 注册自定义异常处理器:

打开 app/Exceptions/Handler.php 文件,

并将 report 和 render 方法中的异常处理逻辑迁移到自定义异常处理器中。

<?php
namespace App\Exceptions;
use Exception;
use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
class Handler extends ExceptionHandler
{
    protected $dontReport = [
        // ...
    ];
    protected $dontFlash = [
        // ...
    ];
    public function register()
    {
        $this->reportable(function (Exception $exception) {
            //
        });
    }
    public function render($request, Exception $exception)
    {
        if ($this->shouldReport($exception)) {
            return app(CustomExceptionHandler::class)->render($request, $exception);
        }
        return parent::render($request, $exception);
    }
}


3. 创建异常处理器中间件:

创建一个异常处理器中间件,用于在全局范围内处理异常。

可以在 app/Http/Middleware 目录下创建一个新的中间件类,

例如 HandleExceptions.php。

<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Contracts\Debug\ExceptionHandler;
class HandleExceptions
{
    protected $handler;
    public function __construct(ExceptionHandler $handler)
    {
        $this->handler = $handler;
    }
    public function handle($request, Closure $next)
    {
        return $this->handler->render($request, $next($request));
    }
}


4. 注册异常处理器中间件:

打开 app/Http/Kernel.php 文件,并将异常处理器中间件添加到 $middleware 数组中。

<?php
namespace App\Http;
use Illuminate\Foundation\Http\Kernel as HttpKernel;
class Kernel extends HttpKernel
{
    protected $middleware = [
        // ...
        \App\Http\Middleware\HandleExceptions::class,
    ];
    // ...
}


5. 日志记录:

Laravel 默认已经配置了日志记录。确保在 config/logging.php 文件中的 channels 配置

中有一个适当的日志通道,以记录异常信息。

在 config/logging.php 文件中,可以添加一个新的日志通道,例如 exceptions:


'channels' => [
    // ...
    'exceptions' => [
        'driver' => 'daily',
        'path' => storage_path('logs/exceptions.log'),
        'level' => 'error',
    ],
],

在自定义异常处理器类的 render 方法中,可以使用日志记录器来记录异常信息:

use Illuminate\Support\Facades\Log;
public function render($request, Exception $exception)
{
    Log::channel('exceptions')->error($exception->getMessage());
    return parent::render($request, $exception);
}

这样,当发生异常时,异常信息将被记录到 storage/logs/exceptions.log 文件中。


6. 自定义异常响应:

可以根据需要,为不同类型的异常定义自定义的响应格式。

在自定义异常处理器类的 render 方法中,根据异常的类型返回不同的错误响应。

public function render($request, Exception $exception)
{
    if ($exception instanceof CustomException) {
      // 获取到自定义类的 data 数据
      // $data = $exception->data;
      
        return response()->json([
            'error' => 'Custom Error',
            'message' => $exception->getMessage(),
        ], 400);
    }
    return parent::render($request, $exception);
}


7. 异常分类和处理:

根据异常的类型或来源,将异常进行分类,并为每个分类定义相应的处理逻辑。

在自定义异常处理器类的 render 方法中,根据异常的类型执行特定的处理操作。

public function render($request, Exception $exception)
{
    if ($exception instanceof DatabaseException) {
        // 处理数据库异常
    } elseif ($exception instanceof ApiException) {
        // 处理 API 异常
    } else {
        // 默认处理逻辑
    }
    return parent::render($request, $exception);
}


8. 友好的错误页面:

可以创建一个自定义的错误页面,用于显示异常信息。

在自定义异常处理器类的 render 方法中,根据异常的类型或状态码返回相应的错误视图。

public function render($request, Exception $exception)
{
    if ($this->isHttpException($exception)) {
        return response()->view('errors.custom', [], $exception->getStatusCode());
    }
    return parent::render($request, $exception);
}


9. 异常监控和报警:

可以使用 Laravel 提供的监控和报警工具,如 Laravel Telescope、Sentry 等,来监控和报警异常情况。

以下是一个使用 Sentry 的示例:

首先,安装 Sentry SDK:

composer require sentry/sentry-laravel

在 .env 文件中,配置 Sentry 的 DSN:

SENTRY_DSN=your-sentry-dsn

在 config/app.php 文件中,将 Sentry\Laravel\ServiceProvider::class 添加到 providers 数组中。

然后,可以在自定义异常处理器类的 render 方法中使用 Sentry 来报告异常:

use Illuminate\Support\Facades\Log;
use Sentry\State\HubInterface;
public function render($request, Exception $exception)
{
    app(HubInterface::class)->captureException($exception);
    return parent::render($request, $exception);
}

这样,当发生异常时,Sentry 将捕获并报告异常信息。


10. 单元测试:

编写针对异常处理逻辑的单元测试,确保异常处理器的正确性和稳定性。

可以使用 Laravel 提供的测试工具,如 PHPUnit,编写测试用例来覆盖不同类型的异常情况。

可以使用 Laravel 提供的 PHPUnit 测试框架编写单元测试用例来验证异常处理器的正确性和稳定性。

以下是一个简单的示例:

创建一个测试类,例如 ExceptionHandlingTest.php,继承自 TestCase:

use Tests\TestCase;
class ExceptionHandlingTest extends TestCase
{
    public function testCustomException()
    {
        $response = $this->get('/custom-exception');
        $response->assertStatus(400);
        $response->assertJson([
            'error' => 'Custom Error',
        ]);
    }
}

在测试类中,编写测试方法来模拟触发自定义异常,并验证异常处理器的响应。

在 routes/web.php 文件中,定义一个路由来触发自定义异常:

Route::get('/custom-exception', function () {
    throw new CustomException('Custom Error');
});

运行单元测试:

php artisan test

以上是关于日志记录、异常监控和报警以及单元测试的简单示例。

根据实际需求和使用的工具,可以进一步扩展和定制这些功能。


  • 上一条:
    用于Laravel的ChatGPT Mock API生成器
    下一条:
    在go语言中封装rabbitmq服务,实现正常、延时消息发送功能
  • 昵称:

    邮箱:

    0条评论 (评论内容有缓存机制,请悉知!)
    最新最热
    • 分类目录
    • 人生(杂谈)
    • 技术
    • linux
    • Java
    • php
    • 框架(架构)
    • 前端
    • ThinkPHP
    • 数据库
    • 微信(小程序)
    • Laravel
    • Redis
    • Docker
    • Go
    • swoole
    • Windows
    • Python
    • 苹果(mac/ios)
    • 相关文章
    • Laravel 11.15版本发布 - Eloquent Builder中添加的泛型(0个评论)
    • Laravel 11.14版本发布 - 新的字符串助手和ServeCommand改进(0个评论)
    • Laravel 11.12版本发布 - Artisan的`make`命令自动剪切`.php `扩展(0个评论)
    • Laravel的轻量型购物车扩展包:binafy/laravel-cart(0个评论)
    • Laravel 11.11版本发布 - 查看模型中的第三方关系:show(0个评论)
    • 近期文章
    • 在go中实现一个常用的先进先出的缓存淘汰算法示例代码(0个评论)
    • 在go+gin中使用"github.com/skip2/go-qrcode"实现url转二维码功能(0个评论)
    • 在go语言中使用api.geonames.org接口实现根据国际邮政编码获取地址信息功能(1个评论)
    • 在go语言中使用github.com/signintech/gopdf实现生成pdf分页文件功能(0个评论)
    • gmail发邮件报错:534 5.7.9 Application-specific password required...解决方案(0个评论)
    • 欧盟关于强迫劳动的规定的官方举报渠道及官方举报网站(0个评论)
    • 在go语言中使用github.com/signintech/gopdf实现生成pdf文件功能(0个评论)
    • Laravel从Accel获得5700万美元A轮融资(0个评论)
    • 在go + gin中gorm实现指定搜索/区间搜索分页列表功能接口实例(0个评论)
    • 在go语言中实现IP/CIDR的ip和netmask互转及IP段形式互转及ip是否存在IP/CIDR(0个评论)
    • 近期评论
    • 122 在

      学历:一种延缓就业设计,生活需求下的权衡之选中评论 工作几年后,报名考研了,到现在还没认真学习备考,迷茫中。作为一名北漂互联网打工人..
    • 123 在

      Clash for Windows作者删库跑路了,github已404中评论 按理说只要你在国内,所有的流量进出都在监控范围内,不管你怎么隐藏也没用,想搞你分..
    • 原梓番博客 在

      在Laravel框架中使用模型Model分表最简单的方法中评论 好久好久都没看友情链接申请了,今天刚看,已经添加。..
    • 博主 在

      佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 @1111老铁这个不行了,可以看看近期评论的其他文章..
    • 1111 在

      佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 网站不能打开,博主百忙中能否发个APP下载链接,佛跳墙或极光..
    • 2016-10
    • 2016-11
    • 2017-07
    • 2017-08
    • 2020-03
    • 2020-04
    • 2020-05
    • 2020-06
    • 2020-07
    • 2020-08
    • 2020-09
    • 2020-10
    • 2020-11
    • 2021-01
    • 2021-02
    • 2021-03
    • 2021-04
    • 2021-05
    • 2021-06
    • 2021-07
    • 2021-08
    • 2021-09
    • 2021-10
    • 2021-11
    • 2021-12
    • 2022-01
    • 2022-02
    • 2022-03
    • 2022-04
    • 2022-05
    • 2022-06
    • 2022-07
    • 2022-08
    • 2022-09
    • 2022-10
    • 2022-11
    • 2022-12
    • 2023-01
    • 2023-02
    • 2023-03
    • 2023-04
    • 2023-05
    • 2023-06
    • 2023-07
    • 2023-08
    • 2023-09
    • 2023-10
    • 2023-11
    • 2023-12
    • 2024-01
    • 2024-02
    • 2024-03
    • 2024-04
    • 2024-05
    • 2024-06
    • 2024-07
    Top

    Copyright·© 2019 侯体宗版权所有· 粤ICP备20027696号 PHP交流群

    侯体宗的博客