Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Api Problem Laravel Package

phpro/api-problem

View on GitHub
Deep Wiki
Context7

Travis Installs Packagist

Api Problem

This package provides a RFC7807 Problem details implementation. It can be integrated everywhere in your code and should result in a general error response format for HTTP APis.

This package only provides a generic interface, an exception class and some built-in api problem messages. Since handling the exceptions is up to the framework, here is a list of known framework integrations:

Installation

composer require phpro/api-problem

Usage

This package provides a general interface for creating ApiProblem value objects.

use Phpro\ApiProblem\Exception;

throw new ApiProblemException(
    new HttpApiProblem(418, ['detail' => 'Did you know 4,000 people are injured by teapots every year?!'])
);

Built-in problems

ExceptionApiProblem

Debuggable: The exception part will only be added in debug context!

use Phpro\ApiProblem\Http\ExceptionApiProblem;

new ExceptionApiProblem(new \Exception('message', 500));
{
  "status": 500,
  "type": "http:\/\/www.w3.org\/Protocols\/rfc2616\/rfc2616-sec10.html",
  "title": "Internal Server Error",
  "detail": "message",
  "exception": {
    "message": "message",
    "type": "RuntimeException",
    "code": 500,
    "line": 23,
    "file": "exception.php",
    "trace": [
         "#0 [internal function]: ...",
         "#1 [internal function]: ...",
         "#3 [internal function]: ...",
         "..."
    ],
    "previous": [
      {
        "message": "previous",
        "type": "InvalidArgumentException",
        "code": 0,
        "line": 20,
        "file": "exception.php",
        "trace": [
            "#0 [internal function]: ...",
            "#1 [internal function]: ...",
            "#3 [internal function]: ...",
            "..."
        ]
      }
    ]
  }
}

HttpApiProblem

use Phpro\ApiProblem\Http\HttpApiProblem;

new HttpApiProblem(404, ['detail' => 'The book could not be found.']);
{
    "status": 404,
    "type": "http:\/\/www.w3.org\/Protocols\/rfc2616\/rfc2616-sec10.html",
    "title": "Not found",
    "detail": "The book could not be found."
}

ValidationApiProblem

composer require symfony/validator:^4.1
use Phpro\ApiProblem\Http\ValidationApiProblem;
use Symfony\Component\Validator\ConstraintViolation;
use Symfony\Component\Validator\ConstraintViolationList;

new ValidationApiProblem(new ConstraintViolationList([
    new ConstraintViolation('Invalid email', '', [], '', 'email', '', null, '8615ecd9-afcb-479a-9c78-8bcfe260cf2a'),
]));
{
    "status": 400,
    "type": "https:\/\/symfony.com\/errors\/validation",
    "title": "Validation Failed",
    "detail": "email: Invalid Email",
    "violations": [
        {
            "propertyPath": "email",
            "title": "Invalid email",
            "type": "urn:uuid:8615ecd9-afcb-479a-9c78-8bcfe260cf2a"
        }
    ]
}

BadRequestProblem

use Phpro\ApiProblem\Http\BadRequestProblem;

new BadRequestProblem('Bad request. Bad!.');
{
    "status": 400,
    "type": "http:\/\/www.w3.org\/Protocols\/rfc2616\/rfc2616-sec10.html",
    "title": "Bad Request",
    "detail": "Bad request. Bad!"
}

UnauthorizedProblem

use Phpro\ApiProblem\Http\UnauthorizedProblem;

new UnauthorizedProblem('You are not authorized to access X.');
{
    "status": 401,
    "type": "http:\/\/www.w3.org\/Protocols\/rfc2616\/rfc2616-sec10.html",
    "title": "Unauthorized",
    "detail": "You are not authenticated. Please login."
}

ForbiddenProblem

use Phpro\ApiProblem\Http\ForbiddenProblem;

new ForbiddenProblem('Not authorized to access gold.');
{
  "status": 403,
  "type": "http:\/\/www.w3.org\/Protocols\/rfc2616\/rfc2616-sec10.html",
  "title": "Forbidden",
  "detail": "Not authorized to access gold."
}

NotFoundProblem

use Phpro\ApiProblem\Http\NotFoundProblem;

new NotFoundProblem('The book with ID 20 could not be found.');
{
    "status": 404,
    "type": "http:\/\/www.w3.org\/Protocols\/rfc2616\/rfc2616-sec10.html",
    "title": "Not found",
    "detail": "The book with ID 20 could not be found."
}

MethodNotAllowedProblem

use Phpro\ApiProblem\Http\MethodNotAllowedProblem;

new MethodNotAllowedProblem('Only POST and GET allowed.');
{
    "status": 405,
    "type": "http:\/\/www.w3.org\/Protocols\/rfc2616\/rfc2616-sec10.html",
    "title": "Method Not Allowed",
    "detail": "Only POST and GET allowed."
}

ConflictProblem

use Phpro\ApiProblem\Http\ConflictProblem;
new ConflictProblem('Duplicated key for book with ID 20.');
{
    "status": 409,
    "type": "http:\/\/www.w3.org\/Protocols\/rfc2616\/rfc2616-sec10.html",
    "title": "Conflict",
    "detail": "Duplicated key for book with ID 20."
}

PreconditionFailedProblem

use Phpro\ApiProblem\Http\PreconditionFailedProblem;

new PreconditionFailedProblem('Incorrect entity tag provided.');
{
    "status": 412,
    "type": "http:\/\/www.w3.org\/Protocols\/rfc2616\/rfc2616-sec10.html",
    "title": "Precondition Failed",
    "detail": "Incorrect entity tag provided."
}

UnsupportedMediaTypeProblem

use Phpro\ApiProblem\Http\UnsupportedMediaTypeProblem;

new UnsupportedMediaTypeProblem('Please provide valid JSON.');
{
    "status": 415,
    "type": "http:\/\/www.w3.org\/Protocols\/rfc2616\/rfc2616-sec10.html",
    "title": "Unsupported Media Type",
    "detail": "Please provide valid JSON."
}

IAmATeapotProblem

use Phpro\ApiProblem\Http\IAmATeapotProblem;

new IAmATeapotProblem('More tea please.');
{
    "status": 418,
    "type": "http:\/\/www.w3.org\/Protocols\/rfc2616\/rfc2616-sec10.html",
    "title": "I'm a teapot",
    "detail": "More tea please."
}

UnprocessableEntityProblem

use Phpro\ApiProblem\Http\UnprocessableEntityProblem;

new UnprocessableEntityProblem('Unable to process the contained instructions.');
{
    "status": 422,
    "type": "http:\/\/www.w3.org\/Protocols\/rfc2616\/rfc2616-sec10.html",
    "title": "Unprocessable Entity",
    "detail": "Unable to process the contained instructions."
}

LockedProblem

use Phpro\ApiProblem\Http\LockedProblem;

new LockedProblem('This door is locked.');
{
    "status": 423,
    "type": "http:\/\/www.w3.org\/Protocols\/rfc2616\/rfc2616-sec10.html",
    "title": "Locked",
    "detail": "This door is locked."
}

PreconditionRequiredProblem

use Phpro\ApiProblem\Http\PreconditionRequiredProblem;

new PreconditionRequiredProblem('If-match header is required.');
{
    "status": 428,
    "type": "http:\/\/www.w3.org\/Protocols\/rfc2616\/rfc2616-sec10.html",
    "title": "Precondition Required",
    "detail": "If-match header is required."
}

Creating your own problem

Creating problem sounds scary right!? Since the RFC is very loose, we made the interface as easy as possible:

use Phpro\ApiProblem\ApiProblemInterface;

class MyProblem implements ApiProblemInterface
{
    public function toArray(): array
    {
        return [
            'type' => 'about:blank',
            'status' => '99',
            'title' => 'Got 99 problems but a glitch aint one!',
        ];
    }
}

A lot of problems will be detected in an HTTP context. Therefore, we also provided a base HttpApiProblem class. This one will automatically fill in the type and title section based on the HTTP code. The only thing you'll need to do, is add some additional data to it:

use Phpro\ApiProblem\Http\HttpApiProblem;

class MyProblem extends HttpApiProblem
{
    public function __construct(string $details)
    {
        parent::__construct(500, ['details' => $details]);
    }
}

If you want to log additional information in a debug context, it is possible to implement an additional DebuggableApiProblemInterface:

use Phpro\ApiProblem\DebuggableApiProblemInterface;

class MyProblem implements DebuggableApiProblemInterface
{
    public function toArray(): array
    {
        return [
            'type' => 'about:blank',
            'status' => '99',
            'title' => 'Got 99 problems but a glitch ain\'t one!',
        ];
    }

    public function toDebuggableArray(): array
    {
        return array_merge(
            $this->toArray(),
            [
                'situation' => 'If you are having code problems, I feel bad for you son',
            ]
        );
    }
}

About

Submitting bugs and feature requests

Bugs and feature request are tracked on GitHub. Please take a look at our rules before contributing your code.

License

api-problem is licensed under the MIT License.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
terminal42/code-quality-tools
codifyo/ts-generator-bundle
andydefer/laravel-cluster
testo/fiber
mintobit/jobqueue
a4sex/maintenance-bundle
a4sex/entity-date-update
a4sex/client-identifier
a4sex/base-utilites
a4sex/key-value-storage
a4sex/micro-status
chilldev/dependency-injection-extra
datinglibre/datinglibre-app-api
biberltd/corebundle
bricre/symfony-bundle-test
biberltd/logbundle
dominium/http-adapter-bundle
dominium/google-analytics
a4sex/auto-clean-entity
christhompsontldr/laravel-inky