wunderwerkio/jsonapi-error

Simple class to conveniently create a JSON error that complies with the JSON:API specification.

0.1.4 2024-06-10 09:22 UTC

This package is auto-updated.

Last update: 2024-07-10 09:34:52 UTC


README

Test Quality Gate Status

This package provides JsonApiError and JsonApiErrorResponse classses to conveniently handle errors following the JSON:API specification.

The JsonApiErrorResponse extends the JsonResponse from symfony/http-foundation, so this package is meant to be used in projects using that.

Table of contents:

Install

Install this package via composer:

composer require wunderwerkio/jsonapi-error

Usage

Return a simple error response

<?php

use Symfony\Component\HttpFoundation\Response;
use Wunderwerk\JsonApiError\JsonApiErrorResponse;

function someRequestHandler(): Response {
  return JsonApiErrorResponse::fromArray([
    'code' => 'application_error_code',
    'title' => 'An error occured!',
    'status' => 500,
  ]);
}

The above code would result in a JSON response with the following payload:

{
  "errors": [{
    "status": 500,
    "code": "application_error_code",
    "title": "An error occured!"
  }]
}

Return multiple errors

<?php

use Symfony\Component\HttpFoundation\Response;
use Wunderwerk\JsonApiError\JsonApiErrorResponse;

function someRequestHandler(): Response {
  return JsonApiErrorResponse::fromArrayMultiple([
    [
      'status' => 422,
      'code' => 'validation_failed',
      'title' => 'Invalid request payload',
      'detail' => 'The "name" field is required.',
      'source' => [
        'pointer' => '/data/name'
      ]
    ],
    [
      'status' => 422,
      'code' => 'validation_failed',
      'title' => 'Invalid request payload',
      'detail' => 'The "description" field is required.',
      'source' => [
        'pointer' => '/data/description'
      ]
    ],
  ]);
}

The above code would result in a JSON response with the following payload:

{
  "errors": [{
    "status": 422,
    "code": "validation_failed",
    "title": "Invalid request payload",
    "detail": "The \"name\" field is required.",
    "source": {
      "pointer": "/data/name"
    }
  }, {
    "status": 422,
    "code": "validation_failed",
    "title": "Invalid request payload",
    "detail": "The \"description\" field is required.",
    "source": {
      "pointer": "/data/description"
    }
  }]
}

Build response from JsonApiError objects

To ease building a response with multiple errors, the response can also be created by constricting it by passing an array of JsonApiError objects.

<?php

use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Response;
use Wunderwerk\JsonApiError\JsonApiError;
use Wunderwerk\JsonApiError\JsonApiErrorResponse;

function someRequestHandler(Request $request): Response {
  /** @var JsonApiError[] $errors */
  $errors = [];

  $payload = $request->getContent();
  $entity = json_decode($payload, TRUE);

  // Make sure 'name' field is set.
  if (!array_key_exists('name', $entity['data'])) {
    $errors[] = JsonApiError::fromArray([
      'status' => 422,
      'code' => 'validation_failed',
      'title' => 'Invalid request payload',
      'detail' => 'The "name" field is required.',
      'source' => [
        'pointer' => '/data/name',
      ],
    ]);
  }

  // Make sure 'description' field is set.
  if (!array_key_exists('description', $entity['data'])) {
    $errors[] = JsonApiError::fromArray([
      'status' => 422,
      'code' => 'validation_failed',
      'title' => 'Invalid request payload',
      'detail' => 'The "description" field is required.',
      'source' => [
        'pointer' => '/data/description',
      ],
    ]);
  }

  if (!empty($errors)) {
    return new JsonApiErrorResponse($errors);
  }

  return new JsonResponse([
    'status' => 'success',
  ]);
}

Local Development

A local dev environment without the need to have PHP locally installed can be done via DDEV.

ddev start

Run tests

ddev composer test

Lint with PHPStan

ddev composer analyze

Credits

This project took inspiration from the following awesome projects: