sfelix-martins/json-exception-handler

增强Laravel异常处理器功能,以处理JSON响应

v2.3.0 2020-07-14 23:46 UTC

README

StyleCI Scrutinizer Code Quality Build Status

为您的 App\Exceptions\Handler 添加方法以处理JSON响应。如果您正在构建API,这非常有用!

要求

  • Laravel框架 >= 5.4
  • php >= 7.0

JsonAPI

使用JsonAPI标准进行响应!

特性

默认错误响应

{
  "errors": [
    {
      "status": "404",
      "code": "13",
      "title": "model_not_found_exception",
      "detail": "User not found",
      "source": {
        "pointer": "data/id"
      }
    }
  ]
}

针对 Illuminate\Validation\ValidationException

{
  "errors": [
    {
      "status": "422",
      "code": "1411",
      "title": "Required validation failed on field name",
      "detail": "The name field is required.",
      "source": {
        "pointer": "name"
      }
    },
    {
      "status": "422",
      "code": "1421",
      "title": "Email validation failed on field email",
      "detail": "The email must be a valid email address.",
      "source": {
        "pointer": "email"
      }
    }
  ]
}

处理的异常

  • Illuminate\Auth\Access\AuthorizationException
  • Illuminate\Auth\AuthenticationException
  • Illuminate\Database\Eloquent\ModelNotFoundException
  • Illuminate\Validation\ValidationException
  • Laravel\Passport\Exceptions\MissingScopeException
  • League\OAuth2\Server\Exception\OAuthServerException
  • Symfony\Component\HttpKernel\Exception\NotFoundHttpException
  • Symfony\Component\HttpKernel\Exception\BadRequestHttpException

安装和配置

安装包

$ composer require sfelix-martins/json-exception-handler

如果您不是使用 Laravel 5.5 版本,请将 JsonHandlerServiceProvider 添加到您的 config/app.php 提供者数组中

    'providers' => [
        ...
        SMartins\Exceptions\JsonHandlerServiceProvider::class,
    ],

发布配置以设置您自己的异常代码

$ php artisan vendor:publish --provider="SMartins\JsonHandler\JsonHandlerServiceProvider"

config/json-exception-handler.php 的代码数组中设置您的异常代码。

您可以在 validation_fields 数组中添加更多字段和代码。

您还可以添加模型到lang包中,以便返回正确的翻译响应。

resources/lang/vendor/exception/lang/$localeexceptions 文件中,您可以在 models 数组中设置。例如:

    'models' => [
        'User' => 'Usuário',
        'Article' => 'Artigo',
    ]

使用

在您的 App\Exception\Handler 上使用特性,并在 render() 方法中传递 $exception,如果 $request 预期JSON响应。

use SMartins\Exceptions\JsonHandler;

class Handler extends ExceptionHandler
{
    use JsonHandler;

    // ...

    public function render($request, Exception $exception)
    {   
        if ($request->expectsJson()) {
            return $this->jsonResponse($exception);
        }

        return parent::render($request, $exception);
    }
    
    // ...

使用示例

class UserController extends Controller
{
    // ...

    public function store(Request $request)
    {
        // Validation
        $request->validate($this->rules);

        // or
        $this->validate($request, $this->rules);

        //and or
        Validator::make($request->all(), $this->rules)->validate();

        if (condition()) {
            // Generate response with http code and message
            abort(403, 'Action forbidden!');
        }

        if (anotherCondition()) {
            // Generate response with message and code
            throw new TokenMismatchException("Error Processing Request", 10);
        }
    }

    public function show($id)
    {
        // If not found the default response is called
        $user = User::findOrFail($id);
        
        // Gate define on AuthServiceProvider
        // Generate an AuthorizationException if fail
        $this->authorize('users.view', $user->id);
    }

扩展

您也可以为任何异常创建自己的处理器。例如:

  • 创建一个继承自 AbstractHandler 的处理器类
namespace App\Exceptions;

use GuzzleHttp\Exception\ClientException;
use SMartins\Exceptions\Handlers\AbstractHandler;

class GuzzleClientHandler extends AbstractHandler
{
    /**
     * Create instance using the Exception to be handled.
     *
     * @param \GuzzleHttp\Exception\ClientException $e
     */
    public function __construct(ClientException $e)
    {
        parent::__construct($e);
    }
}
  • 您必须实现 AbstractHandler 类的 handle() 方法。该方法必须返回 ErrorErrorCollection 的实例
namespace App\Exceptions;

use SMartins\Exceptions\JsonAPI\Error;
use SMartins\Exceptions\JsonAPI\Source;
use GuzzleHttp\Exception\ClientException;
use SMartins\Exceptions\Handlers\AbstractHandler;

class GuzzleClientHandler extends AbstractHandler
{
    // ...

    public function handle()
    {
        return (new Error)->setStatus($this->getStatusCode())
            ->setCode($this->getCode())
            ->setSource((new Source())->setPointer($this->getDefaultPointer()))
            ->setTitle($this->getDefaultTitle())
            ->setDetail($this->exception->getMessage());
    }

    public function getCode()
    {
        // You can add a new type of code on `config/json-exception-handlers.php`
        return config('json-exception-handler.codes.client.default');
    }
}
namespace App\Exceptions;

use SMartins\Exceptions\JsonAPI\Error;
use SMartins\Exceptions\JsonAPI\Source;
use SMartins\Exceptions\JsonAPI\ErrorCollection;
use SMartins\Exceptions\Handlers\AbstractHandler;

class MyCustomizedHandler extends AbstractHandler
{
    public function __construct(MyCustomizedException $e)
    {
        parent::__construct($e);
    }

    public function handle()
    {
        $errors = (new ErrorCollection)->setStatusCode(400);

        $exceptions = $this->exception->getExceptions();

        foreach ($exceptions as $exception) {
            $error = (new Error)->setStatus(422)
                ->setSource((new Source())->setPointer($this->getDefaultPointer()))
                ->setTitle($this->getDefaultTitle())
                ->setDetail($exception->getMessage());

            $errors->push($error);
        }

        return $errors;
    }
}
  • 现在只需在 App\Exception\Handler 文件上的 exceptionHandlers 属性中注册您的自定义处理器。例如:
namespace App\Exceptions;

use Exception;
use GuzzleHttp\Exception\ClientException;
use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
use SMartins\Exceptions\JsonHandler;

class Handler extends ExceptionHandler
{
    use JsonHandler;

    protected $exceptionHandlers = [
        // Set on key the exception and on value the handler.
        ClientException::class => GuzzleClientHandler::class,
    ];

响应引用