A relationship endpoint, such as /articles/1/relationships/author, returns only the linkage of a relationship (the type and id of the related one) and lets you change it. You write the routes and the controllers; the package validates the shape of the document and builds the response.
Still under validation. Relationships, included and relationship endpoints are tested with a complete reference API inside the package tests, which validate every response against the official JSON:API schema. They have not been validated in a real application yet. If something does not fit, open an issue.
Reading a relationship
A Relationship returned from a controller is the response of a relationship endpoint: {jsonapi, links, data, meta} with only the linkage.
public function author(string $article) {
$model = Article::query()->with('author')->findOrFail($article);
return Relationship::one($model->author, AuthorResource::class)->links(
self: route('articles.relationships.author', [$model]),
related: route('articles.author', [$model]),
);
}
Writing a relationship
To write a relationship, read the linkage with RelationshipDocument: the package has already validated its shape (see Reading the input document). What depends on your model you check yourself, with these codes:
| Situation | Status | source. |
|---|---|---|
| A list where a single identifier goes | 422 | /data |
The type is not the one of the relationship | 409 | /data/type |
| The related resource does not exist | 404 | /data |
use MundoProgra\JsonApi\Exceptions\JsonApiException;
use MundoProgra\JsonApi\Http\Requests\RelationshipDocument;
public function updateAuthor(Request $request, string $article) {
$document = RelationshipDocument::of($request); // data() is null, an identifier or a list; isList() says which
if ($document->isList()) { // a list where an identifier goes
throw JsonApiException::make(status: 422, detail: 'A to-one relationship takes one identifier or null.', pointer: '/data');
}
$identifier = $document->data(); // ['type' => 'authors', 'id' => '3'] or null
if ($identifier !== null && $identifier['type'] !== 'authors') {
throw JsonApiException::make(status: 409, pointer: '/data/type'); // the type is not the relationship's
}
$author = $identifier === null ? null : Author::find($identifier['id'])
?? throw JsonApiException::make(status: 404, pointer: '/data'); // the resource does not exist
// ... associate, save and answer with the resulting relationship (`200`)
}
What each verb does
PATCHreplaces the relationship.POSTadds elements to a to-many relationship.DELETEremoves elements from a to-many relationship.
Check everything before writing, so an error does not leave half-made changes.
The complete example, with reads, writes and errors, is in tests/Fixtures/ReferenceApi. The error codes are in Errors.