In Symfony 6.3 we introduced a feature to map request data into typed objects
using the #[MapRequestPayload]
and #[MapQueryString]
attributes. However,
sometimes you want to map individual request data to specific controller arguments.
Symfony has allowed to map route parameters to controller arguments since its
first version. In Symfony 6.3 you will also be able to map query string parameters
to specific controller arguments. To do so, use the new #[MapQueryParameter]
attribute:
1 2 3 4 5 6 7 8 9
#[Route(path: '/', name: 'admin_dashboard')]
public function indexAction(
#[MapQueryParameter] array $ids,
#[MapQueryParameter] string $firstName,
#[MapQueryParameter] bool $required,
#[MapQueryParameter] int $age,
#[MapQueryParameter] string $category = '',
#[MapQueryParameter] ?string $theme = null,
)
If the query string of the incoming request is /?ids[]=1&ids[]=2&firstName=Ruud&required=3&age=123
,
this code will make the controller arguments to have these values:
1 2 3 4 5 6
$ids = ['1', '2']
$firstName = "Ruud"
$required = false
$age = 123
$category = ''
$theme = null
The #[MapQueryParameter]
attribute makes the conversion of the query string
parameter(which is always a string) into the proper PHP type according to the
types of your controller arguments (it's similar to calling
$request->query->getInt('...')
, $request->query->getAlpha('...')
, etc.
but automated by Symfony).
For more advanced use cases, you can use the filter
option of the attribute
to validate the data type details:
1 2 3 4 5 6 7
// this ensures that the array only contains integer values
#[MapQueryParameter(filter: \FILTER_VALIDATE_INT)]
array $ids
// this ensures that the string follows some specific pattern
#[MapQueryParameter(filter: \FILTER_VALIDATE_REGEXP, options: ['regexp' => '/^\w++$/'])]
string $name
Awesome !!!
Thanks for this!
Thanks a lot for this amazing feature!
Nice feature 👍
It is cool! Keep it up
Thank you for this. Very useful!
Very nice addition 👌🏻
These request changes for 6.3 are awesome!
Give me a way to map request headers to be deserialized now and I imagine you’ll have hit every point (and that would be awesome for APIs that do challenges based on headers).
@Richard Lynskey: You mean something like
#[MapRequestHeader('X-API-Key')] $apiKey
?If I'm correct, this should also work with `\FILTER_SANITIZE_* sanitization filters...?
Nice!!
Love to see how Symfony gets better and better every release 💪🏻
Very useful addition 💪
So I tried to add a last argument to my action, like this: #[MapQueryParameter] ?int $page = 1 If I don't pass "page" in the query string, I get:
Controller "App\Controller\MyController::index" requires that you provide a value for the "$page" argument. Either the argument is nullable and no null value has been provided, no default value has been provided or because there is a non optional argument after this one.
So, apart from the wrong wording in the error (the "because" is non-sense, and "non optional" should be written as "non-optional", it just doesn't work.
About my previous comment: I found that the bug is already fixed in Symfony 6.3 (but not in the beta yet). I opened a bug about the incorrect wording.