Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RequiredIf validator with multiple values fails validating boolean 0 #36952

Closed
Norgul opened this issue Apr 12, 2021 · 11 comments
Closed

RequiredIf validator with multiple values fails validating boolean 0 #36952

Norgul opened this issue Apr 12, 2021 · 11 comments
Labels

Comments

@Norgul
Copy link
Contributor

Norgul commented Apr 12, 2021

  • Laravel Version: 8.36.2
  • PHP Version: 7.4.1
  • Database Driver & Version: not related to the issue

Description:

Since boolean validation rule accepts and validates several boolean value variants I wanted to enable required_if validator to accept and validate against those values as well, however it fails having 0 as a value.

Steps To Reproduce:

Correct behavior 1:

// Validation
'some_bool_field' => 'required|boolean',
'check_against_1' => 'required_if:some_bool_field,true',
'check_against_2' => 'required_if:some_bool_field,false',

// Payload
'some_bool_field' => true, // will trigger 'check_against_1'
'some_bool_field' => false, // will trigger 'check_against_2'

Correct behavior 2:

// Validation
'some_bool_field' => 'required|boolean',
'check_against_1' => 'required_if:some_bool_field,1',
'check_against_2' => 'required_if:some_bool_field,0',

// Payload
'some_bool_field' => 1, // will trigger 'check_against_1'
'some_bool_field' => 0, // will trigger 'check_against_2'

Invalid behavior:

// Validation
'some_bool_field' => 'required|boolean',
'check_against_1' => 'required_if:some_bool_field,1,true',
'check_against_2' => 'required_if:some_bool_field,0,false',

// Payload
'some_bool_field' => true, // will trigger 'check_against_1'
'some_bool_field' => false, // will trigger 'check_against_2'
'some_bool_field' => 1, // will trigger 'check_against_1'

'some_bool_field' => 0, // should trigger 'check_against_2', but triggers both
@driesvints
Copy link
Member

It only triggers check_against_2 for me:

Validator::make(['some_bool_field' => 0], [
    'some_bool_field' => 'required|boolean',
    'check_against_1' => 'required_if:some_bool_field,1,true',
    'check_against_2' => 'required_if:some_bool_field,0,false',
]);
{
  "check_against_2": [
    "The check against 2 field is required when some bool field is 0."
  ]
}

@Norgul
Copy link
Contributor Author

Norgul commented Apr 12, 2021

@driesvints for which Laravel version?

Doing exactly what you did:

Route::get('test', function(){
    Validator::make(['some_bool_field' => 0], [
        'some_bool_field' => 'required|boolean',
        'check_against_1' => 'required_if:some_bool_field,1,true',
        'check_against_2' => 'required_if:some_bool_field,0,false',
    ])->validate();
});

And the response:

{
    "message": "The given data was invalid.",
    "errors": {
        "check_against_1": [
            "The check against 1 field is required when some bool field is 0."
        ],
        "check_against_2": [
            "The check against 2 field is required when some bool field is 0."
        ]
    }
}

@driesvints
Copy link
Member

@Norgul I get a validation exception for that code. Laravel v8.36.2

@driesvints
Copy link
Member

Screenshot 2021-04-13 at 11 44 34

@Norgul
Copy link
Contributor Author

Norgul commented Apr 13, 2021

@driesvints you are doing it wrong. You are dumping the current rule only. Run my exact route to reproduce.

@driesvints
Copy link
Member

I did run your exact code.

@Norgul
Copy link
Contributor Author

Norgul commented Apr 13, 2021

@driesvints but you are showing a dump, not a response?

@driesvints
Copy link
Member

This is the validation exception I get when calling the validate method from your code example. In your route example you're not returning anything.

@Norgul
Copy link
Contributor Author

Norgul commented Apr 13, 2021

@driesvints Try putting it within api routes without dumping, so that you'll get 422 with all error messages.

@calkeo
Copy link

calkeo commented Apr 13, 2021

If you call this within the API middleware with the correct Accept: application/json header, then I also receive the validation exception for both check_against_1 and check_against_2 when using the string boolean representation i.e. true/false.

For example:

Validator::make(['some_bool_field' => 0], [
        'some_bool_field' => 'required|boolean',
        'check_against_1' => 'required_if:some_bool_field,true',
        'check_against_2' => 'required_if:some_bool_field,false',
    ])->validate();

Returns

{
    "message": "The given data was invalid.",
    "errors": {
        "check_against_1": [
            "The check against 1 field is required when some bool field is 0."
        ],
        "check_against_2": [
            "The check against 2 field is required when some bool field is 0."
        ]
    }
}

Whereas

Validator::make(['some_bool_field' => 0], [
        'some_bool_field' => 'required|boolean',
        'check_against_1' => 'required_if:some_bool_field,1',
        'check_against_2' => 'required_if:some_bool_field,0',
    ])->validate();

Returns

{
    "message": "The given data was invalid.",
    "errors": {
        "check_against_2": [
            "The check against 2 field is required when some bool field is 0."
        ]
    }
}

However, the behaviour is different when running PHP 8 vs PHP 7.4. PHP 8 correctly evaluates the string values true/false as booleans, whereas 7.4 does not.

@driesvints
Copy link
Member

I can indeed confirm that the difference in PHP version was the culprit. This seems like another regression introduced by #36504 and related to #36540.

I've attempted a fix here: #36967

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants