在Laravel项目中Exception(异常处理)优化最佳实践方式浅析
Laravel  /  管理员 发布于 1年前   967
在开发 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
以上是关于日志记录、异常监控和报警以及单元测试的简单示例。
根据实际需求和使用的工具,可以进一步扩展和定制这些功能。
123 在
Clash for Windows作者删库跑路了,github已404中评论 按理说只要你在国内,所有的流量进出都在监控范围内,不管你怎么隐藏也没用,想搞你分..原梓番博客 在
在Laravel框架中使用模型Model分表最简单的方法中评论 好久好久都没看友情链接申请了,今天刚看,已经添加。..博主 在
佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 @1111老铁这个不行了,可以看看近期评论的其他文章..1111 在
佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 网站不能打开,博主百忙中能否发个APP下载链接,佛跳墙或极光..路人 在
php中使用hyperf框架调用讯飞星火大模型实现国内版chatgpt功能示例中评论 教程很详细,如果加个前端chatgpt对话页面就完美了..Copyright·© 2019 侯体宗版权所有· 粤ICP备20027696号