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