Thanks to visit codestin.com
Credit goes to github.com

Skip to content

[RFC][HttpFoudation] Add a better way to handle invalid values and default values. #60901

Open
@Growiel

Description

@Growiel

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:

  1. Add a third parameter to getInt() and getBoolean(): array $options to allows to pass any arbitrary options to the underlying filter() 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 how filter_var() works to make it work. Does not address the default value issue (you still need to provide it as an option of filter_var in case of failure AND as $default to handle a non-existing value).
  2. Add a third parameter to getInt() and getBoolean(): 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.
  3. Add a third parameter to getInt() and getBoolean(): 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 an UnexpectedValueException 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.

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    HttpFoundationRFCRFC = Request For Comments (proposals about features that you want to be discussed)

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions