mnavarrocarter/problem-details

一个与框架无关的RFC7807实现

0.1.2 2018-04-04 15:29 UTC

This package is auto-updated.

Last update: 2024-09-05 19:01:53 UTC


README

ApiException是一个用于PHP的抽象异常类,实现了RFC7807问题详情结构。

它旨在扩展到其他异常类,这些类定义了特定的错误类型,根据RFC的规定。

安装

简单执行

composer require mnavarrocarter/problem-details

使用方法

创建自定义异常类型

对于API中的不同问题类型,您必须创建有意义的异常类,这些类将扩展此抽象类,并重写构造函数以设置自定义类型、标题,如果需要,还可以设置状态码。

<?php

namespace App\Errors;

use MNC\ProblemDetails\ApiException;

class AuthenticationProblemException extends ApiException
{
    public function __construct(string $detail = '', array $extra = [], ?\Throwable $previous = null)
    {
        $type = 'errors/authentication';
        $title = 'Authentication Error';
        $statusCode = 401;
        parent::__construct($type, $title, $statusCode, $detail, $extra, $previous);
    }
}

使用工厂模式简化错误创建。

现在,创建您的类后,您可以使用工厂模式快速简单地创建您刚刚创建的自定义错误类型的新实例。

<?php

namespace App\Errors;

use MNC\ProblemDetails\ApiException;

class AuthenticationProblemException extends ApiException
{
    public function __construct(string $detail = '', array $extra = [], ?\Throwable $previous = null)
    {
        $type = 'errors/authentication';
        $title = 'Authentication Error';
        $statusCode = 401;
        parent::__construct($type, $title, $statusCode, $detail, $extra, $previous);
    }
    
    public static function invalidCredentials(array $sentCredentials)
    {
        return new self(
            'Invalid credentials',
            $sentCredentials  
        );
    }
}

然后,在客户端代码中

<?php

namespace App\Services;

use App\Error\AuthenticationProblemException;

class Authenticator extends ApiException
{
    public function authenticate(array $sentCredentials)
    {
        if ($this->areValidCredentials($sentCredentials)) {
            return $this->findUser($sentCredentials);
        }
        throw AuthenticationProblemException::invalidCredentials($sentCredentials);
    }
}

然后,在控制器级别,您可以通过捕获这些异常来提供响应。或者,如果您使用像Symfony这样的框架,您可以配置异常监听器。

<?php

namespace App\Controller;

use MNC\ProblemDetails\ApiException;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;

class SomeController extends Controller
{
    public function someAction(Request $request)
    {
        try {
            $variable = $this->tryAction($request);
        } catch (ApiException $e) {
            return $this->json($e, $e->getStatusCode());
        }
        return $variable;
    }
}

如果您注意到,ApiException实现了PHP的\JsonSerializable接口。因此,它可以通过简单的json_encode()轻松序列化。如果您只想规范化对象,可以调用toArray()方法。

修改实现

tldr; 您不能。不过,您可以实现该接口。

此实现非常封闭。属性可见性对您隐藏,您只能通过公共方法与属性交互。

此外,实现方法被声明为final,因此您不能覆盖它们。这将保护您免受破坏,因为这个类是为了通过检查获取器和设置器中的内容始终提供有意义的响应而开发的。

接口存在是为了让您创建自己的实现。