Skip to content
MundoProgra JSON:API
Menu

Guide

Reading the input document

The package validates the body of write requests before they reach your controller. This page explains what it validates, how to read the document and how to write the validation rules with a FormRequest.

What is validated

The package validates the body of every JSON POST and PATCH before it reaches your controller, and the DELETE of a relationship endpoint too (PUT only with allow_put). If the document is not JSON or does not have the shape of a JSON:API document, it answers 400 with the exact source.pointer of the failing member; an id sent by the client when creating is a 403 unless you turn on allow_client_ids.

How to read it

To read it, the request has these methods (attribute and relationship names are in snake_case):

MethodReturns
$request->isJsonApi()Whether the package treats the request as JSON:API
$request->jsonApiType() / jsonApiId()The type and id of the document (id is null if absent)
$request->jsonApiAttributes()The attributes, with names in snake_case
$request->hasJsonApiRelationship('author')Whether the client sent that relationship (even as data: null)
$request->jsonApiRelationshipId('author')The id of a to-one relationship, or null
$request->jsonApiRelationshipIds('tags')The ids of a to-many relationship, in order

Without the name, jsonApiRelationshipId() and jsonApiRelationshipIds() read the linkage of the body of a relationship endpoint (see Relationship endpoints).

Validating with a FormRequest

Add the InteractsWithJsonApi trait and write the rules over the flat data of the document: attributes in snake_case and, for each relationship, its object. validated() can fill a model and each error comes out with its source.pointer:

use Illuminate\Foundation\Http\FormRequest;
use MundoProgra\JsonApi\Http\Requests\InteractsWithJsonApi;

class StoreArticleRequest extends FormRequest {
  use InteractsWithJsonApi;

  public function authorize(): bool {
    return true;
  }

  public function rules(): array {
    return [
      'title' => ['required', 'string', 'max:50'],        // /data/attributes/title
      'status' => ['sometimes', 'in:draft,published'],    // /data/attributes/status
      'author.data.id' => ['integer'],                    // /data/relationships/author/data/id
      'tags.data.*.type' => ['in:labels'],                // /data/relationships/tags/data/0/type
    ];
  }

  // The `type` this endpoint accepts: any other is a 409. And on PATCH/PUT, the `id` must be the one in the URL
  // (jsonApiExpectedId(), by default the last route parameter).
  protected function jsonApiExpectedType(): ?string {
    return 'articles';
  }
}

Only what has a rule reaches validated(). An attribute of the document without a rule is ignored: it is not assigned to the model, and the response is the same as if you had not sent it. It is a useful protection if your model allows mass assignment, but you have to remember to write a rule for every attribute you want to accept.

A validation error

A repeated value in a unique column, for example, answers like this (with the application locale set to Spanish):

{
  "jsonapi": { "version": "1.1" },
  "errors": [
    {
      "status": "422",
      "code": "mundoprogra.json-api.validation.unique",
      "title": "Falló la validación",
      "detail": "The email has already been taken.",
      "source": { "pointer": "/data/attributes/email" }
    }
  ]
}

The detail is the Laravel rule's message, in your application's language; see Known limits. The other error codes, such as the 409 for a different type, are in Errors.