Hi! Loving the library — using it for an API where resources are intentionally exposed only under a parent for
access-control clarity. I've hit a structural limitation when trying to emit JSON:API-spec links.related on relationships of these
nested resources, and wanted to start a conversation before potentially upstreaming a fix.
The pattern
URLs are deliberately festival-scoped (no top-level /categories):
GET /festivals/{fid}/extra-fields
GET /festivals/{fid}/extra-fields/{id}
GET /festivals/{fid}/extra-fields/{id}/category ← what I want
The first two work today via a custom ShowChildResource endpoint registered on FestivalsResource, plus a FindableInParent interface on
the child collection. ShowChildResource::handle() builds the correct self link manually and overlays it onto the document after
serializeResourceDocument():
$selfLink = implode('/', [
$context->api->basePath,
$context->collection->name(),
$context->id($context->resource, $context->model),
$relationshipName,
$childId,
]);
$document['links']['self'] ??= $selfLink;
This gives the resource a correct self link in the response.
What doesn't work: links.related on the resource's relationships
I'd like the rendered extra-field to expose:
"category": {
"data": { "type": "extra-field-categories", "id": "1216" },
"links": { "related": "/api/festivals/1/extra-fields/5793/category" }
}
The standard ShowRelated::relationshipLinks() builds the URL as resourceSelfLink($model, $context) . '/' . $field->name, where
resourceSelfLink() is hardcoded:
// Endpoint/Concerns/ResolvesModel.php
protected function resourceSelfLink($model, Context $context): string
{
return implode('/', [
$context->api->basePath,
$context->collection->name(),
$context->id($context->resource, $context->model),
]);
}
For a top-level resource that produces /api/extra-fields/5793 — not what users actually hit. The relationship-link callback runs
during serialization and doesn't have access to the parent festival id, so I can't compose /api/festivals/1/extra-fields/5793/category
from there.
The relationship-link emission also walks ProvidesRelationshipLinks endpoints, but the standard ones (ShowRelated, ShowRelationship)
are gated on the parent collection being top-level, so they don't fire for these nested cases.
What I'd hope for
A way to tell the library that a resource has a parent context, such that:
- resourceSelfLink() produces the correct multi-segment URL
- relationshipLinks() callbacks emit URLs derived from that self link
- ToOne links.related works without per-app workarounds
I don't want to prescribe an API — there are several reasonable shapes (a ParentScoped interface on collections, a nestedSelfLink()
override, a Context-level "ancestor chain", etc.). Wanted to gauge interest before opening a PR.
Why it matters
We're publishing this API for AI agents and third-party integrations to consume. JSON:API's links.related is the spec-blessed way for
clients to navigate without out-of-band URL knowledge — without it, every consumer has to read the OpenAPI spec, learn URL templates,
and stitch in parent ids. With it, "follow the link" Just Works.
The pattern is endorsed by the spec (the JSON:API examples show /articles/1/relationships/author style nesting throughout), and
several other libraries in other languages support it natively, so I expect this isn't unique to my use case.
Happy to discuss, draft a PR, or just leave this here for visibility. Thanks for the library.
Hi! Loving the library — using it for an API where resources are intentionally exposed only under a parent for
access-control clarity. I've hit a structural limitation when trying to emit JSON:API-spec links.related on relationships of these
nested resources, and wanted to start a conversation before potentially upstreaming a fix.
The pattern
URLs are deliberately festival-scoped (no top-level /categories):
GET /festivals/{fid}/extra-fields
GET /festivals/{fid}/extra-fields/{id}
GET /festivals/{fid}/extra-fields/{id}/category ← what I want
The first two work today via a custom ShowChildResource endpoint registered on FestivalsResource, plus a FindableInParent interface on
the child collection. ShowChildResource::handle() builds the correct self link manually and overlays it onto the document after
serializeResourceDocument():
This gives the resource a correct self link in the response.
What doesn't work: links.related on the resource's relationships
I'd like the rendered extra-field to expose:
The standard ShowRelated::relationshipLinks() builds the URL as resourceSelfLink($model, $context) . '/' . $field->name, where
resourceSelfLink() is hardcoded:
For a top-level resource that produces /api/extra-fields/5793 — not what users actually hit. The relationship-link callback runs
during serialization and doesn't have access to the parent festival id, so I can't compose /api/festivals/1/extra-fields/5793/category
from there.
The relationship-link emission also walks ProvidesRelationshipLinks endpoints, but the standard ones (ShowRelated, ShowRelationship)
are gated on the parent collection being top-level, so they don't fire for these nested cases.
What I'd hope for
A way to tell the library that a resource has a parent context, such that:
I don't want to prescribe an API — there are several reasonable shapes (a ParentScoped interface on collections, a nestedSelfLink()
override, a Context-level "ancestor chain", etc.). Wanted to gauge interest before opening a PR.
Why it matters
We're publishing this API for AI agents and third-party integrations to consume. JSON:API's links.related is the spec-blessed way for
clients to navigate without out-of-band URL knowledge — without it, every consumer has to read the OpenAPI spec, learn URL templates,
and stitch in parent ids. With it, "follow the link" Just Works.
The pattern is endorsed by the spec (the JSON:API examples show /articles/1/relationships/author style nesting throughout), and
several other libraries in other languages support it natively, so I expect this isn't unique to my use case.
Happy to discuss, draft a PR, or just leave this here for visibility. Thanks for the library.