Skip to content

feat(metadata): add parameter name to uriVariablesConverter context - #8431

Open
jannes-io wants to merge 1 commit into
api-platform:4.4from
jannes-io:feat-parametername-in-transform-context
Open

feat(metadata): add parameter name to uriVariablesConverter context#8431
jannes-io wants to merge 1 commit into
api-platform:4.4from
jannes-io:feat-parametername-in-transform-context

Conversation

@jannes-io

Copy link
Copy Markdown
Contributor
Q A
Branch? 4.4
Tickets
License MIT
Doc PR

Adds the parameter name of the variable that's currently being processed to the context so custom implementations of UriVariableTransformerInterface can do something with it.

Our immediate use-case is that we have a uri variable that's a base64 encoded classname for a foreign entity, say:

#[GetCollection(
    uriTemplate: '/blips/{targetClass}/{foreignKey}',
    uriVariables: ['targetClass', 'foreignKey'],
)]
class Blip {}

The targetClass value is actually just a base64 encoded string, and it's also stored in the database. If we just use it like this (using symfony/doctrine), it will create the query with the correct parameters, but the value for targetClass remains b64 encoded.

We can get around that by adding a custom uri variables transformer:

class BlipUriVariableTransformer implements UriVariableTransformerInterface
{
    public function supportsTransformation(mixed $value, array $types, array $context = []): bool
    {
        $operation = $context['operation'] ?? null;
        return $operation instanceof GetCollection && $operation->getClass() === Blip::class;
    }

    // ...
}

But this also triggers for the foreign key argument, so we need to base64 decode, and then check if the class exists, during the transformation itself:

    public function transform(mixed $value, array $types, array $context = []): string
    {
        $newValue = base64_decode($value);
        if (class_exists($newValue)) {
            return $newValue;
        }
        return $value;
    }

This is not very clean... 😞

So this pull requests adds the current parameter name that's being transformed to the context, which will change our implementation to:

class BlipUriVariableTransformer implements UriVariableTransformerInterface
{
    public function supportsTransformation(mixed $value, array $types, array $context = []): bool
    {
        $operation = $context['operation'] ?? null;
        if (!$operation instanceof GetCollection || $operation->getClass() !== Blip::class) {
            return false;
        }
        return ($context['parameterName'] ?? null) === 'targetClass';
    }

    public function transform(mixed $value, array $types, array $context = []): string
    {
        return base64_decode($value);
    }
}

Very nice! 👍

I've also noticed there wasn't a unit test yet for UriVariablesConverter, so I just added one but it only validates that the parameterName is temporarily available in the context and not overwritten outside of it.

@jannes-io
jannes-io force-pushed the feat-parametername-in-transform-context branch from 328b28a to f72672a Compare July 29, 2026 13:32
Comment thread composer.json
"justinrainbow/json-schema": "^6.5.2",
"laravel/framework": "^11.0 || ^12.0 || ^13.0",
"mcp/sdk": "^0.6",
"mcp/sdk": "^0.7",

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Needed to change this to have a valid installable state,... without this all workflows and local composer install result in a non-resolvable set of dependencies.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I initially wanted to add it as a fully qualified parameter to both the supports and transform functions, but that would be a backwards compatibility break.

Comment on lines +63 to +64
$paramContext = $context;
$paramContext['parameterName'] = $parameterName;

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is just so we don't overwrite anything that might've been added by the user to the context. The context remains the same outside of this function.

Downside? We have to copy the entire context array for every uri variable, so there might be a tiny performance overhead. Could also check outside of the foreach and keep whatever value was set out there, and reset it again after the foreach.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant