Download the PHP package stetodd/jsonapi-bundle without Composer
On this page you can find all versions of the php package stetodd/jsonapi-bundle. It is possible to download/install these versions without Composer. Possible dependencies are resolved automatically.
Download stetodd/jsonapi-bundle
More information about stetodd/jsonapi-bundle
Files in stetodd/jsonapi-bundle
Package jsonapi-bundle
Short Description JSON:API request mapping and response serialisation for Symfony, built on league/fractal
License MIT
Informations about the package jsonapi-bundle
stetodd/jsonapi-bundle
JSON:API request mapping and response serialisation for Symfony, built on league/fractal.
Install
Register in config/bundles.php:
Configure in config/packages/stetodd_json_api.yaml:
Responses
Inject Stetodd\JsonApiBundle\Response\JsonApiResponder into controllers:
Resources implement Contract\IdentifiableResourceInterface (getId(): \Stringable|string). Each resource gets a transformer extending League\Fractal\TransformerAbstract and implementing Contract\ResourceTransformerInterface; transformers are auto-registered via autoconfiguration — no tagging needed.
Paginated collections take any Contract\PagedResultInterface. A fresh Fractal manager is built per response, so no include state leaks between requests (worker-mode safe).
Query features
The JSON:API query families are parsed by Request\Query\JsonApiQuery::fromRequest() and honoured per request:
?include=— include paths are validated against the root transformer's available + default includes; an unsupported path is a400(per spec). Valid paths are passed to Fractal'sparseIncludes.?fields[type]=— sparse fieldsets, applied to the primary resource and included resources via Fractal'sparseFieldsets. Per the spec, fieldsets restrict relationships too: relationship links are only emitted for relationships named in the type's fieldset.-
?sort=— declare a resource's sortable fields on its transformer:then inject
Request\Query\SortResolverinto the list action and translate the validated sorts into your ordering:An undeclared sort field is a
400(per spec). The mapping of field names to a concrete ordering stays in the application. ?page[number]=/?page[size]=— parsed ontoJsonApiQuery->pageNumber/pageSizefor the application's pagination resolver; the responder's pagination links emit the same shape (preservingpage[size]).?filter[...]=— deliberately not interpreted by the bundle: filter strategy is application-defined. Convention: a list-query DTO with afilterproperty mapped via Symfony's#[MapQueryString], so?filter[x]=nests naturally.
Auto-registered relationship endpoints
Declare a resource's URL prefix and relationships on its transformer:
then import the route loader (before your attribute controllers, so a hand-written route with the same name — e.g. a POST relationship update — wins):
Each declaration registers GET {path}/{id}/relationships/{segment} (resource
linkage) and GET {path}/{id}/{segment} (full related resource), named to the
configured relationship_routes patterns — the same ones the serializer builds
relationship links from, so links and endpoints stay in lockstep. The relationship
data is fetched through the transformer's own Fractal include{Name}() method; the
URL segment is the kebab-cased name (fileUpload → file-upload, overridable via
pathSegment:).
The application provides one service: an implementation of
Contract\RelationshipSourceResolverInterface, which loads the parent resource by
id and enforces access control (return null → 404; throw an
AccessDeniedException → 403). Alias the interface to your implementation:
Error objects
HttpExceptions raised on JSON:API routes are rendered as spec error objects
(application/vnd.api+json):
Validation failures (a ValidationFailedException as the exception's previous,
which the mapping attributes and #[MapQueryString]/#[MapRequestPayload] all
produce) yield one error per violation, with source.parameter for query input on
safe methods and source.pointer for body input. Non-HTTP throwables (genuine
500s) keep Symfony's default handling, so debug traces survive in dev.
Content negotiation
Per the spec's server responsibilities, requests on JSON:API routes are rejected
when they misuse the JSON:API media type itself: a Content-Type: application/vnd.api+json modified with media type parameters is a 415, and an
Accept header where every instance of the JSON:API media type carries
parameters is a 406 (q is ignored). Other media types — e.g. plain
application/json — pass through untouched. Both rejections render as JSON:API
error objects.
Which routes count as JSON:API (for error rendering and content negotiation) is decided by route-name prefix:
Conformance assertions
Test\JsonApiAssertionsTrait (requires phpunit in your dev dependencies) provides
spec-shape assertions for use in any test — one conformance test per surface
catches structural regressions cheaply:
Resource self links
#[JsonApiResource(path: …)] also drives each resource's links.self: the
serializer emits {base_url}{path}/{id} (e.g. /geospatial/locations/{id})
instead of Fractal's naive {base_url}/{type}/{id}, so transformers don't build
self links by hand. A links key returned from transform() still wins — use it
for resources with non-standard URLs (e.g. /profile/me).
Requests
Map JSON:API payloads onto DTOs with controller argument attributes:
Attribute DTOs implement Request\AttributesDTOInterface (use AttributesDTOTrait), relationship DTOs implement Request\RelationshipsDTOInterface. When a controller maps both, they are bound together through Request\Context / ContextBindingInterface (use ContextBindingTrait). Payloads are validated with symfony/validator; failures return 422 with violation messages.
All versions of jsonapi-bundle with dependencies
league/fractal Version ^0.20.1
symfony/config Version ^7.2|^8.0
symfony/dependency-injection Version ^7.2|^8.0
symfony/event-dispatcher Version ^7.2|^8.0
symfony/http-foundation Version ^7.2|^8.0
symfony/http-kernel Version ^7.2|^8.0
symfony/routing Version ^7.2|^8.0
symfony/serializer Version ^7.2|^8.0
symfony/string Version ^7.2|^8.0
symfony/translation-contracts Version ^3.0
symfony/validator Version ^7.2|^8.0