core icon indicating copy to clipboard operation
core copied to clipboard

Unable to generate an IRI for "XYZ" when "identifiers" attribute is used

Open mleko64 opened this issue 4 years ago • 3 comments

API Platform version(s) affected: 2.6.4

Description
According to this https://github.com/api-platform/core/blob/main/docs/adr/0001-resource-identifiers.md I'm using a identifiers property on item operation (on @ApiResource directly not works) and in documentation is everything OK (I have endpoint with {id} placeholder instead {shortName}), because in core/src/Bridge/Symfony/Routing/ApiLoader.php file on line 231 there is condition to check if $operation['identifiers'] is already set. And that is OK.

Problem is, if I call this endpoint, I have a error: Unable to generate an IRI for "App\Entity\User" Error is triggered in core/src/Bridge/Symfony/Routing/IriConverter.php file on line 156, because $this->router->generate(..) produces an error: "Some mandatory parameters are missing ("id") to generate a URL for route "api_user_get_item".". I checked what is in the variable $identifiers which is passed as second argument to router generator and there is:

array:1 [
  "shortName" => "1"
]

I think the key should be id instead of shortName. I checked where this value comes from and in core/src/Bridge/Symfony/Routing/IriConverter.php file on line 121 is used identifiersExtractor to get identifiers name/values, but this extractor not care about identifiers attribute (set in annotations) at all. This extractor only looks for a property in the class marked as "identifier" and reads its name (defined in the class) and the value.

How to reproduce
Create a entity/resource like this:

/**
 * @ApiResource(
 *    itemOperations={
 *       "get"={
 *          "identifiers"={"id"={User::class, "shortName"}})  
 *       }
 *    }
 */
 class User {
  /** @ApiProperty(identifier=true) */
  public string $shortName;
 }

Make a call to GET endpoint to recieve User.

Thank you for your help.

mleko64 avatar Apr 19 '21 11:04 mleko64

I have the same issue with API Platform: 2.6.8. The only difference is the use of "attributes"

/**
 * @ApiResource(
 *    collectionOperations = {
 *        "get",
 *    },
 *    itemOperations =  {
 *        "get",
 *    },
 *    attributes = {
 *        "identifiers": {"_site" : {Site::class, "name"}}
 *    }  
 *)
 */
final class Site
{
    public int $id;

    /**
     * @ApiProperty(identifier = true)
     */
    public string $name;

morban avatar Apr 22 '22 10:04 morban

Hello, I reproduced this bug with the following class :

#[ORM\Entity]
#[ApiResource(itemOperations: ['get' => ['identifiers' => ['id' => [User::class, 'shortName']]]])]
class User {
    #[ORM\Id]
    #[ORM\GeneratedValue]
    #[ORM\Column(type: 'integer')]
    #[ApiProperty)]
    public int $id;

    #[ORM\Column(type: 'string')]
    #[ApiProperty(identifier: true)]
    public string $shortName = '';
}

I fixed it by:

  • Replacing ['get' => ['identifiers' => ['id' => [User::class, 'shortName']] by ['get' => ['identifiers' => ['shortName' => [User::class, 'shortName']] or just ['get']
  • Adding identifier: false on $id property (if exists)

Jean-Beru avatar Apr 27 '22 11:04 Jean-Beru

I have adding identifier: false on $id property but it still doesn't work (NB:I don't use ORM\Entity, I use DataProvider).

morban avatar Apr 28 '22 08:04 morban

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

stale[bot] avatar Nov 04 '22 21:11 stale[bot]

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

stale[bot] avatar Jan 04 '23 01:01 stale[bot]