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. of the failing member; an id sent by the client when creating is a 403 unless you turn on allow_.
How to read it
To read it, the request has these methods (attribute and relationship names are in snake_case):
| Method | Returns |
|---|---|
$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.:
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.