-
-
Notifications
You must be signed in to change notification settings - Fork 934
Description
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.