Skip to content

feat(metadata): resource and operation level itemUriTemplate - #8479

Open
Amoifr wants to merge 1 commit into
api-platform:mainfrom
Amoifr:feat-8075-item-uri-template
Open

feat(metadata): resource and operation level itemUriTemplate#8479
Amoifr wants to merge 1 commit into
api-platform:mainfrom
Amoifr:feat-8075-item-uri-template

Conversation

@Amoifr

@Amoifr Amoifr commented Aug 24, 2026

Copy link
Copy Markdown

Implements the plan laid out in #8075 (comment) (resource + operation itemUriTemplate), closes #8075.

When an item operation has a custom uriTemplate (new Patch(uriTemplate: '/purchases/{id}/billing-address')), the response @id reuses that URI instead of the canonical one. itemUriTemplate existed only on Post and GetCollection; this lifts it up:

  • Op-level: itemUriTemplate moves to HttpOperation (with getItemUriTemplate()/withItemUriTemplate()), so Get, Patch and Put accept it; Post and GetCollection keep their signature and delegate.
  • Resource-level: ApiResource gains itemUriTemplate as a DRY default; the propagation to operations is automatic through the generic cascadeFromResource()/copyFrom() mechanism, with op-level precedence (op ?? resource ?? null).
  • IriConverter (Symfony and Laravel; Mcp delegates): when the resolved operation is a non-collection HttpOperation carrying an itemUriTemplate, the target operation is resolved through OperationMetadataFactory::create(). The block is skipped when $context['item_uri_template'] was already resolved at the top of the method, which avoids a double resolution through the cascaded template of the target operation (caught by the functional test on op-level precedence).
  • Extractors: XML + YAML support itemUriTemplate at the resource level, and the op-level whitelist accepts Get, Patch and Put (it threw before); XSD updated.
  • Serializer context: nothing to change, SerializerContextBuilder, OperationContextTrait and the JSON:API ItemNormalizer already feed item_uri_template through method_exists($operation, 'getItemUriTemplate').

Additive, no behavior change when the option is unset. Covered by a unit test on the Symfony IriConverter and a functional test (CanonicalIriTest) asserting the canonical @id for a PATCH with a custom URI, both with the resource-level default and with an op-level override taking precedence. The exhaustive ResourceMetadataCompatibilityTest covers the new resource property through the XML/YAML adapters.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

IRI of entities with custom controller contain route/path information

1 participant