Skip to content

Validation issue with multiple query parameters using :property templates + property restrictions #7460

@DavidBennettUK

Description

@DavidBennettUK

API Platform version(s) affected: 4.2.2

Description
When defining an operation's parameters, if multiple parameter keys use the :property placeholder with property restrictions, then it will only be possible to use properties defined in the very first parameter.

How to reproduce
Resource:

<?php

declare(strict_types=1);

namespace App\Api\Resource;

use ApiPlatform\Metadata\ApiProperty;
use ApiPlatform\Metadata\ApiResource;
use ApiPlatform\Metadata\GetCollection;
use ApiPlatform\Metadata\Link;
use ApiPlatform\Metadata\QueryParameter;
use App\Api\Filter\Array\OrderFilter;
use App\Api\Filter\Array\PartialSearchFilter;
use App\Api\State\Provider\DummyProvider;

#[ApiResource(
    operations: [
        new GetCollection(
            parameters: [
                'search[:property]' => new QueryParameter(
                    filter: new PartialSearchFilter(),
                    properties: [
                        'name',
                    ],
                ),
                'order[:property]' => new QueryParameter(
                    filter: new OrderFilter(),
                    properties: [
                        'count',
                    ],
                ),
            ],
        ),
    ],
    provider: DummyProvider::class,
)]
final readonly class Dummy
{
    public function __construct(
        #[ApiProperty(identifier: true)]
        public int $id,
        public string $name,
        public int $count,
    ) {}
}

In the API doc, both search[name] and order[count] show up correctly as query parameters. Using ?search[name]=something on the query works fine. But using ?order[count]=desc does not work, resulting in the following error:

{
  "@context": "/api/contexts/ConstraintViolation",
  "@id": "/api/validation_errors/7703c766-b5d5-4cef-ace7-ae0dd82304e9",
  "@type": "ConstraintViolation",
  "status": 422,
  "violations": [
    {
      "propertyPath": "order[count]",
      "message": "This field was not expected.",
      "code": "7703c766-b5d5-4cef-ace7-ae0dd82304e9"
    }
  ],
  "detail": "order[count]: This field was not expected.",
  "description": "order[count]: This field was not expected.",
  "type": "/validation_errors/7703c766-b5d5-4cef-ace7-ae0dd82304e9",
  "title": "An error occurred"
}

Possible Solution
The validation error comes from the Collection validator constraint that is set up here. It relies on _properties in extraProperties listing the correct allowed fields for the parameter.

However, _properties is not correct due to a bug with the localPropertyCache here. This is because $parameter->getKey() is null, so the cache key ends up being just the class name - so the same cache is shared between multiple parameters, causing the issue. The second (and subsequent) parameter will recieve the cache of the first defined parameter.

Commenting out the cache fixes the issue. I'm not sure if the proper fix is to find out why $parameter->getKey() is null, or to change how the cache key is calculated. See #7461 for a potential solution.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions