Open Ilyes512 opened 1 day ago
Nice one, I definitely want to fix this.
can you state your use_symfony_listeners
configuration value ?
Nice one, I definitely want to fix this.
Ah, so you are confirming that multiple ParameterProvider
should be something that works.
can you state your use_symfony_listeners configuration value ?
# relative file path: config/packages/api_platform.yaml
api_platform:
# ...
use_symfony_listeners: false
# ...
Anything I can do to help? In any case I will keep an eye on this issue and I usually can react pretty fast. I think it would be nice to create a clear picture of how we want it to work?
I am currently experimenting locally for a possible fix. If I got something I might just share it here or apply it right away in a fork.
So a possible solution could be https://github.com/api-platform/core/compare/3.4...Ilyes512:api-platform-core:6673-paramater-providers-fix
For now:
class GroupsParameterProvider implements ParameterProviderInterface {
public function provider(Parameter $parameter, array $uriVariables = [], array $context = []): HttpOperation
{
$request = $context['request'];
$request->attributes->set('organization', $this->organizationRepository->find($organizationId));
return $operation;
}
}
Mutating the operation needs to be written into the request attributes, I thought I did in in the ParameterProvider I'll check. Anyways, request attributes are there to store request informations and this works fine.
So mutating the request is the way to go? Or do you mean it more like a temp solution?
My gut feeling says "don't mutate the request", but I know the api-platform already does. So my gut feeling is probably unfounded.
edit:
https://github.com/symfony/http-foundation/blob/6.4/Request.php#L82-L87
I was not familiar with this attribute. It seems to be meant for mutation by the application.
it's a possible solution, even if you change the operation I'll mutation the operation
inside the request attributes :). I know that this works but changing the operation should also work. I'll cherry-pick your commit and add a test tomorrow!
FYI: I have now implemented my providers by setting a value in the attribute bag and that works fine for my use cases đź‘Ť.
API Platform version(s) affected: 3+
Description
If we have 2 different ParameterProviders set to 2 different query parameters, only the last provider has effect on the context/operation. So if I add a new value to the context in the first provider, that change is then not visible in the next provider.
How to reproduce
I have a DTO with a
GetCollection
attribute. In that attribute I have added an array of two QueryParameters to theparameters
-parameter of theGetCollection
attribute.So something like this:
Both
ParameterOneProvider
andParameterTwoProvider
implement theParameterProviderInterface
. In both parameters I do something like this:If we now take a look at the
ApiPlatform\State\Provider\ParameterProvider
we can see that the operation that is returned from the first loop is not given to the next provider. See https://github.com/api-platform/core/blob/cead16a02592e8a2446f72286a6e9d2c3503e2eb/src/State/Provider/ParameterProvider.php#L86-L90The new operation (
$op
) that is returned from the$providerInstance->provide()
call is assigned to the$operator
variable. Using my providers the$provider
instance will always be a new instance since we calledwithNormalizationContext
that usesclone
to return a new instance.Within the loop nothing is really done with the
$operator
except for possibly overwriting it again with a second call to a provider. Only after leaving the loop are we then assigning it to the context https://github.com/api-platform/core/blob/cead16a02592e8a2446f72286a6e9d2c3503e2eb/src/State/Provider/ParameterProvider.php#L97So that means we are only seeing any changes made to the operation from the last provider called.
So unless I have totally misunderstood the use cases for using
ParameterProviderInterface
, what's the point of creating multiple custom providers?Possible Solution
Not really sure if my use case is what the custom ParameterProvider was meant for.
Additional Context
I work on a project where we use DTO's and don't have api-platform directly tight to Doctrine (so we don't make use of the Doctrine integration in our Symfony project).
So my use case for the custom parameter provider is for example to have a query parameter that can contain a string uuid. And what I do is turn that string uuid into a Uuid instance and make it available to the custom provider for the specific DTO. I thought I would be able to do this by setting a unique value on the context so it becomes available in the DTO's provider.
CC: @soyuka (since it seems like you have added this)