Open darthf1 opened 4 months ago
We're also affected by this change. We use the uri variables for later processing but they stopped coming and it breaks a lot of endpoints.
They're removed from the context only in case of a relation. The ApiPlatform\State\UriVariablesResolverTrait
may help you gather URIs for a given operation if needed. Last but not least, you should be able to get initial uri_variables using Symfony's Request no?
They're removed from the context only in case of a relation. The
ApiPlatform\State\UriVariablesResolverTrait
may help you gather URIs for a given operation if needed.
I just tried with adding ApiPlatform\State\UriVariablesResolverTrait
, but the getOperationUriVariables
requires the $operation
to which I don't have access in the denormalizer (right ?).
Last but not least, you should be able to get initial uri_variables using Symfony's Request no?
Accessing via SF request would be possible I guess, Ill try on monday, but that is a lot of extra logic for something which was easily accessible through the context in a previous patch release?
Either you have the operation inside the context or you need to use the ResourceMetadataFactory basicaly it's like:
Ok, so I was able to resolve it most easy with:
private RequestStack $requestStack
$request = $this->requestStack->getCurrentRequest();
/** @var array<string, scalar> $uriVariables */
$uriVariables = $request?->attributes->get('_api_uri_variables', []);
Not sure that this is correct, uri variables are present for the main resource, but when it's a relation we can't know for sure that uri variables are the one from the request. On something else I don't understand why you would need another subsystem for CQRS, API Platform has embedded CQRS (Processor/Provider).
Not sure that this is correct, uri variables are present for the main resource, but when it's a relation we can't know for sure that uri variables are the one from the request. On something else I don't understand why you would need another subsystem for CQRS, API Platform has embedded CQRS (Processor/Provider).
Its only a custom denormalizer, not a full subsystem (right?).
Lets say I have the following command:
<?php
final readonly class CreateEngagementCommand
{
public const string DENORMALIZATION_GROUP = 'engagement_create_denormalize';
public function __construct(
public OrganisationId $organisationId,
#[Groups([self::DENORMALIZATION_GROUP])]
public string $engagementName,
) {}
}
With the following api resource:
<?php
#[ApiResource(
operations: [
new Post(
uriTemplate: '/organisations/{organisationId}/engagements',
uriVariables: [
'organisationId' => new Link(
fromClass: Organisation::class,
fromProperty: 'organsation',
security: "is_granted('" . OrganisationVoter::ATTRIBUTE_ORGANISATION_READ . "', organsation)",
),
],
requirements: [
'organisationId' => AbstractDomainId::REQUIREMENT,
],
messenger: 'input',
input: CreateEngagementCommand::class,
output: false,
status: Response::HTTP_ACCEPTED,
denormalizationContext: [
'groups' => [CreateEngagementCommand::DENORMALIZATION_GROUP],
],
),
],
)
class Engagement {}
Then I perform the following request:
curl -X POST "http://my-api.com/organisations/{organisationId}/engagements" \
-H "Content-Type: application/json" \
-d '{"engagementName": "my engagement"}'
During denormalization it would throw an error, because the $organisationId
property of class CreateEngagementCommand
is not an instance of OrganisationId (because no value is given in the payload, and no value is even allowed to be given because of the denormalization group).
What my denormalizer is doing, besides getting all constructor parameter from the request payload in combination with the given denormalization group, is check if there are any unset constructor parameters left, where the property name is equal to one of the provided uri variables (organisationId in this case), and where the property type is one of a domain id. Thats why I need access to those uri variables.
Well, this is the solution I came up with during my migration from v2.7 to v3. If you have a better / simpler solution I would love to hear it :) I'm still getting accustomed to all the specifics of the new operation classes.
API Platform version(s) affected: 3.3.11
Description I have a custom
Symfony\Component\Serializer\Normalizer\DenormalizerInterface
class, which converts the request context to a typed (CQRS) Command class. Based on the uri variables, the Command constructor arguments are set and based on the type, some additional (constructor) logic is executed.The
CommandDenormalizer
has the following methods:However, when updating from
3.3.7
to3.3.11
, theuri_variables
seems to be missing from$context
.I guess directly related to https://github.com/api-platform/core/pull/6467