core icon indicating copy to clipboard operation
core copied to clipboard

Cannot use new linked resources with using Json LD

Open Geekimo opened this issue 4 months ago • 0 comments

API Platform version(s) affected: 4.4.2

Description
When using the ReadLinkParameterProvider to automatically load parent DTO as an uriVariable, the serialization encounters issues while trying to generate IRI.

How to reproduce

  • Create a DTO that loads another one
<?php

namespace App\ApiResource;

use ApiPlatform\Metadata\ApiProperty;
use ApiPlatform\Metadata\ApiResource;
use ApiPlatform\Metadata\Get;
use ApiPlatform\Metadata\Link;
use ApiPlatform\State\ParameterProvider\ReadLinkParameterProvider;

#[ApiResource(
    operations: [
        new Get(
            uriTemplate: '/hello/{world}',
            uriVariables: [
                'world' => new Link(fromClass: World::class, provider: ReadLinkParameterProvider::class),
            ],
            provider: HelloWorldProvider::class,
        )
    ]
)]
final readonly class TestResource {
    public function __construct(
        #[ApiProperty(identifier: true)]
        public int $id,
    ) {
    }
}

Call /hello/34 (where 34 is World resource identifier value) while accepting application/ld+json. At this point, in my HelloWorldProvider, if World was found, I have a World resource into $operation->getUriVariables()['world'], but $uriVariables['world'] is still (string) 34, and I can return whatever value I want from my provider. If I only accepts application/json, everything works fine. But if I accept application/ld+json, it goes wild and I get an error from Symfony's UrlGenerator regarding the type of one of the arguments used to generate an IRI.

When rebuilding operation's uriVariables in https://github.com/api-platform/core/blob/main/src/Symfony/Controller/MainController.php#L102 , resource class that was previously injected in operation's uriVariables bag is now passed to $uriVariables which is used for serialization context, but when times come to generate resource's IRI, the resource world cannot be used as a value for UrlGenerator.

Possible Solution
When serializing data using https://github.com/api-platform/core/blob/main/src/State/Processor/SerializeProcessor.php#L69 , $uriVariables values that are related to a Link into current Operation should be swapped with their identifier. (Ex: World resource with id 34 should be replaced with 34 instead of the whole object)

Additional Context
Call stack before exception

Image

I found a temporary workaround by adding a __toString method to my World resource that returns it's identifier as string.

I may provide a PR solving this issue during this week.

Geekimo avatar Oct 19 '25 21:10 Geekimo