Description
Description
Hello everyone,
Like a lot of other people, following migration to Symfony 7, we've been plagued with issues like this one: Parameter value "XXX" is invalid and flag "FILTER_NULL_ON_FAILURE" was not set
.
Which requires us to change from the easy to use getInt()
to the much much more verbose: $request->query->filter('XXX', filter: \FILTER_VALIDATE_INT, options: ['flags' => \FILTER_REQUIRE_SCALAR | \FILTER_NULL_ON_FAILURE])
And it gets even worse if we want a default value:
$request->query->filter('page', filter: \FILTER_VALIDATE_INT, options: ['options' => ['default' => 1], 'flags' => \FILTER_REQUIRE_SCALAR | \FILTER_NULL_ON_FAILURE])
I feel like there are two issues with this:
1: It's a lot of work to get a null on invalid values.
2: It's even worse if we want to have a default value on invalid values, because the $default
parameter is ignored, which is really confusing. You have to set it as an option of filter_var
.
What I would like to propose is one of the following:
-
Add a third parameter to
getInt()
andgetBoolean()
:array $options
to allows to pass any arbitrary options to the underlyingfilter()
method.- Pro: Allows to use any flag and retains the strong typing.
- Con: If you set a default value in $options that is not of the right type (an int for
getInt()
), PHP will yell at you (as it should!). You still need a deep understanding of howfilter_var()
works to make it work. Does not address the default value issue (you still need to provide it as an option offilter_var
in case of failure AND as$default
to handle a non-existing value).
-
Add a third parameter to
getInt()
andgetBoolean()
:bool $returnNullOnFailure
. If set to true, in case of invalid value,null
will be returned.- Pro: Super easy to use. Allows to handle default value on failure by using a simple
?? value
. - Con: Would require to change the return type to
?int
or?bool
, which could break a lot of static analysis in people's projects as suddendly a null check must be performed everywhere.
- Pro: Super easy to use. Allows to handle default value on failure by using a simple
-
Add a third parameter to
getInt()
andgetBoolean()
:bool $returnDefaultOnFailure
. If set to true, in case of invalid value, the default value probided in$default
will be returned. If false, the current behavior or throwing anUnexpectedValueException
will be used.- Pro: Super easy to use. Does not require a change in the return type. Handles the default value in case of failure gracefully (only need to set (
$default
)). - Con: Does not allow to get
null
on invalid value.
- Pro: Super easy to use. Does not require a change in the return type. Handles the default value in case of failure gracefully (only need to set (
From what I saw in the multiple post regarding this issue, most people aren't actually concerned with getting a null
on failure, but rather want to get back the Symfony 6.x behavior of returning the default value.
With that in mind, I feel like version 3 offers the best value.
With a simple optional parameter, you can handle invalid values like you used to in previous versions of Symfony.
If you want to keep a strict control and know when an invalid value is passed, you can also do so.
I feel like the same change should be implemented in #[MapQueryParameter]
to avoid this kind of code: #[MapQueryParameter(flags: \FILTER_NULL_ON_FAILURE, options: ['default' => 0])]
and rather just rely on the default value set on the property itself.
I'd be willing to provide a PR for this if I do get the go ahead from the community.
Thanks a lot.
Example
Assume the following request: http://www.example.com/blog?page=aa
.
Before:
With the following code:
$page = $request->query->getInt('page', 1);
echo $page;
Result
UnexpectedValueException: Parameter value "page" is invalid and flag "FILTER_NULL_ON_FAILURE" was not set.
With the following code:
$page = $request->query->filter('page', filter: \FILTER_VALIDATE_INT, options: ['options' => ['default' => 1], 'flags' => \FILTER_REQUIRE_SCALAR | \FILTER_NULL_ON_FAILURE])
echo $page;
Result
1
After:
With the following code (NO CHANGES):
$page = $request->query->getInt('page', 1);
echo $page;
Result
UnexpectedValueException: Parameter value "page" is invalid and flag "FILTER_NULL_ON_FAILURE" was not set.
With the following code:
$page = $request->query->getInt('page', 1, returnDefaultOnFailure: true);
echo $page;
Result
1