项目作者: mnavarrocarter

项目描述 :
A framework agnostic RFC7807 implementation
高级语言: PHP
项目地址: git://github.com/mnavarrocarter/problem-details.git
创建时间: 2018-04-04T14:36:18Z
项目社区:https://github.com/mnavarrocarter/problem-details

开源协议:

下载


ApiException (RFC7807 Implementation)

ApiException is an abstract exception class for php that implements the
RFC7807 problem details structure.

It is ment to be extended into other exception classes that define specific error
types, according to the RFC.

Installing

Simply do:

  1. composer require mnavarrocarter/problem-details

Usage

Creating your custom Exception Types

For the different problem types in your api, you must create meaningful exception
classes that will extend this abstract one, and override the constructor to set
your custom type, title and, if you want, status code.

  1. <?php
  2. namespace App\Errors;
  3. use MNC\ProblemDetails\ApiException;
  4. class AuthenticationProblemException extends ApiException
  5. {
  6. public function __construct(string $detail = '', array $extra = [], ?\Throwable $previous = null)
  7. {
  8. $type = 'errors/authentication';
  9. $title = 'Authentication Error';
  10. $statusCode = 401;
  11. parent::__construct($type, $title, $statusCode, $detail, $extra, $previous);
  12. }
  13. }

Using Factory Pattern to simplify error creation.

Now, with your class created, you can use the factory pattern to quickly and simply
create new instances of the custom error type you just created.

  1. <?php
  2. namespace App\Errors;
  3. use MNC\ProblemDetails\ApiException;
  4. class AuthenticationProblemException extends ApiException
  5. {
  6. public function __construct(string $detail = '', array $extra = [], ?\Throwable $previous = null)
  7. {
  8. $type = 'errors/authentication';
  9. $title = 'Authentication Error';
  10. $statusCode = 401;
  11. parent::__construct($type, $title, $statusCode, $detail, $extra, $previous);
  12. }
  13. public static function invalidCredentials(array $sentCredentials)
  14. {
  15. return new self(
  16. 'Invalid credentials',
  17. $sentCredentials
  18. );
  19. }
  20. }

Then, in your client code:

  1. <?php
  2. namespace App\Services;
  3. use App\Error\AuthenticationProblemException;
  4. class Authenticator extends ApiException
  5. {
  6. public function authenticate(array $sentCredentials)
  7. {
  8. if ($this->areValidCredentials($sentCredentials)) {
  9. return $this->findUser($sentCredentials);
  10. }
  11. throw AuthenticationProblemException::invalidCredentials($sentCredentials);
  12. }
  13. }

Then, at your controller level, you can catch these exceptions to provide a response.
Or, if you use frameworks like Symfony, you can configure an Exception Listener.

  1. <?php
  2. namespace App\Controller;
  3. use MNC\ProblemDetails\ApiException;
  4. use Symfony\Component\HttpFoundation\Request;
  5. use Symfony\Bundle\FrameworkBundle\Controller\Controller;
  6. class SomeController extends Controller
  7. {
  8. public function someAction(Request $request)
  9. {
  10. try {
  11. $variable = $this->tryAction($request);
  12. } catch (ApiException $e) {
  13. return $this->json($e, $e->getStatusCode());
  14. }
  15. return $variable;
  16. }
  17. }

If you noticed, the ApiException implements PHP’s \JsonSerializable interface. So
it is easily serialized with a simple json_encode(). If you want to just normalize
the object, you can call the toArray() method.

Modifiying the implementation

tldr; You can’t. You can implement the interface though.

This implementation is very closed. Property visibility is hidden from you,
and you can only interact with the properties via the public methods.

Also, the implementation methods are declared final, so you can’t override them.
This will protect you from breaking anything, as this class is developed to always
provide a meaningful response by checking stuff in getters and setters.

The interface is there in case you want to create your own implementation.