gsousadev / laravel-problem-detail-exceptions-lib
用于标准化使用 'problem details' 格式的 exceptions 的包
Requires
- php: ^8.1
Requires (Dev)
- orchestra/testbench: v8.1.1
This package is auto-updated.
Last update: 2024-09-09 19:55:00 UTC
README
该项目旨在提供一个Laravel库,允许通过遵循RFC problem details的概念,以简单快捷的方式实现exceptions的标准
安装
可以使用Composer安装此包
composer require gsousadev/laravel-problem-detail-exceptions-lib
安装后,需要发布包的配置文件。使用以下命令来完成此操作
php artisan vendor:publish --tag=problem-detail-exceptions
发布包后,应在以下路径创建一个用于项目的配置文件:/config/problem-detail-exceptions.php。
<?php use Gsousadev\LaravelProblemDetailExceptions\Enums\ExceptionsFieldsEnum; return [ 'app_name' => env('PROBLEM_DETAIL_EXCEPTION_APP_NAME', 'APP'), 'log_throw' => env('PROBLEM_DETAIL_EXCEPTION_GENERATE_LOGS', true), 'available_fields_list' => [ ExceptionsFieldsEnum::TYPE, ExceptionsFieldsEnum::TITLE, ExceptionsFieldsEnum::STATUS, ExceptionsFieldsEnum::DETAIL, ExceptionsFieldsEnum::INTERNAL_CODE, ExceptionsFieldsEnum::MESSAGE, ExceptionsFieldsEnum::USER_MESSAGE, ExceptionsFieldsEnum::USER_TITLE, ExceptionsFieldsEnum::LOCATION, ExceptionsFieldsEnum::TRACE_ID, ExceptionsFieldsEnum::PREVIOUS_MESSAGE, ExceptionsFieldsEnum::PREVIOUS_CODE, ExceptionsFieldsEnum::PREVIOUS_TYPE, ExceptionsFieldsEnum::PREVIOUS_LOCATION ], 'renderable_fields_list' => [ ExceptionsFieldsEnum::TITLE, ExceptionsFieldsEnum::STATUS, ExceptionsFieldsEnum::USER_MESSAGE, ExceptionsFieldsEnum::USER_TITLE, ], ];
配置
此包允许一些自定义配置。为此,应使用文件 problem-detail-exceptions.php
为了在流程中保持数据一致性,非常重要地实现两个环境变量
- PROBLEM_DETAIL_EXCEPTION_APP_NAME : 指示可能出现在日志中的项目或应用程序名称。
- PROBLEM_DETAIL_EXCEPTION_GENERATE_LOGS : 此变量允许在发生错误时开启或关闭要发布的日志。
示例
PROBLEM_DETAIL_EXCEPTION_APP_NAME=nome_do_aplicativo PROBLEM_DETAIL_EXCEPTION_GENERATE_LOGS=true
此外,可以在配置文件中配置哪些字段应考虑为API exceptions的字段
存在两种可能的配置:在任何上下文中应使用的字段 fields 以及在错误响应中应显示的字段 renderable_fields。
注意:不推荐在HTTP响应中使用所有可用字段,因为某些字段可能包含应安全存储或不应向任何人公开的信息。
所有字段都必须根据也位于项目中的Enum类进行注册。
以下Enum中包含可用字段
<?php namespace Gsousadev\LaravelProblemDetailExceptions\Enums; enum ExceptionsFieldsEnum: string { case TYPE = 'type'; case TITLE = 'title'; case STATUS = 'status'; case DETAIL = 'detail'; case INTERNAL_CODE = 'internal_code'; case MESSAGE = 'message'; case USER_MESSAGE = 'user_message'; case USER_TITLE = 'user_title'; case LOCATION = 'location'; case TRACE_ID = 'trace_id'; case PREVIOUS_MESSAGE = 'previous_message'; case PREVIOUS_TYPE = 'previous_type'; case PREVIOUS_CODE = 'previous_code'; case PREVIOUS_LOCATION = 'previous_location'; }
创建自定义Exceptions
为了使用此包,建议创建扩展自 Gsousadev\LaravelProblemDetailExceptions\Exceptions\ProblemDetailException 类的异常,如下所示示例类
... use Gsousadev\LaravelProblemDetailExceptions\Exceptions\ProblemDetailException; class ExampleException extends ProblemDetailException
然后,我们必须在构造函数中对父类构造函数进行调用,传递创建异常所需的所有参数。
... public function __construct(?\Throwable $previous = null) { parent::__construct( title: 'Titulo curto para erro. Deve ser imutável', detail: 'Descrição mais detalhada do erro podendo conter variaveis dinâmicas.' . 'Pode ser mutável a cada lançamento dependendo do contexto', userTitle: 'Titulo amigavel para usuário final que pode ver o erro', userMessage: 'Detalhamento amigavel para usuário que pode ver o erro', httpStatus: 500, internalCode: 'SHRD0001', previous: $previous ); } ...
最终结果应如下所示
<?php declare(strict_types=1); namespace App\Exceptions; use Gsousadev\LaravelProblemDetailExceptions\Exceptions\ProblemDetailException; class ExampleException extends ProblemDetailException { public function __construct(?\Throwable $previous = null) { parent::__construct( title: 'Titulo curto para erro. Deve ser imutável', detail: 'Descrição mais detalhada do erro podendo conter variaveis dinâmicas.' . 'Pode ser mutável a cada lançamento dependendo do contexto', userTitle: 'Titulo amigavel para usuário final que pode ver o erro', userMessage: 'Detalhamento amigavel para usuário que pode ver o erro', httpStatus: 500, internalCode: 'SHRD0001', previous: $previous ); } }
这样,就可以获得一个可读性良好、完整且具有简单直接调用方式的异常。
try { ... } catch(\Exception $exception){ throw new ExampleException($exception); }
异常日志
还可以通过使用 $logThrow 选项配置每个异常的日志。此选项允许我们为每个异常配置是否生成日志,而不管整体配置如何。如果省略,则采用整体日志配置。
示例
... class ExampleException extends ProblemDetailException { protected ?bool $logThrow = true public function __construct(?\Throwable $previous = null) ...
自动标准化Exceptions
存在一个类可以与Laravel的Exceptions Handler一起使用,允许将所有抛出并由handler处理的exceptions转换为并标准化为'Problem Detail'格式。这允许应用程序快速将不同格式的exceptions的输出标准化为日志和HTTP请求。通常,Laravel的handler文件位于此处 App\Exceptions\Handler.php。可以按照以下示例实现此类
<?php namespace App\Exceptions; use Gsousadev\LaravelProblemDetailExceptions\Exceptions\ProblemDetailException; use Gsousadev\LaravelProblemDetailExceptions\Exceptions\UnexpectedException; use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler; use Throwable; class Handler extends ExceptionHandler { public function register() { $this->renderable(function (Throwable $e) { if (!$e instanceof ProblemDetailException) { throw new UnexpectedException($e); } }); } public function report(Throwable $e) { if ($e instanceof ProblemDetailException) { parent::report($e); } } }
贡献
该项目处于建设阶段,改进建议对项目成长非常重要。为了提出改进建议,请使用GitHub的Issue功能。