framework: Validation does not fail when "integer" is checked, on a string
- Laravel Version: 5.4.18
- PHP Version: PHP 7.0.6-1+donate.sury.org~trusty+1 (cli) ( NTS )
- Database Driver & Version: n/a
Description:
When I am trying to validate an string that has only numbers, the validation will pass, when i use the rule “integer”. I expect the validation to fail, because the value is a string, and not integer. ‘5’ => should fail validation 5 => should not fail validation
Steps To Reproduce:
$rules = ['id' => 'integer'];
$validatorFactory = app(\Illuminate\Contracts\Validation\Factory::class);
$validator = $validatorFactory->make(['id' => '5'], $rules);
var_dump($validator->fails());
The result should be true, and not false, because id is string '5'.
Proposed solution
Use
return is_int($value);
instead of current validator:
return filter_var($value, FILTER_VALIDATE_INT) !== false;
or, to avoid breaking backwards compatibility, we need to have the ability to force the validator to be strict.
About this issue
- Original URL
- State: closed
- Created 7 years ago
- Reactions: 1
- Comments: 15 (9 by maintainers)
Reopening this because defending weak typing / casting strings to ints in 2019 as a “feature” is just not on.
@themsaid wrote:
No - it returns a numeric value in string form.
An integer is a data type, not the content of a string. Please don’t conflate a string containing numeric/integer-like values with an integer data type. We aren’t working with PHP 4/5 in 2005 - 2015.
For a modern framework I don’t think it’s acceptable to say “we’re ok with weak typing even though the community is moving away from that”. PHP has made a lot of positive steps towards much stricter typing to weed out problems weak typing causes, and in turn weeding out a lot of criticism of PHP. Calling this a “feature” and having people defend it because “someone needs to ensure there aren’t decimal places on form input” is a little silly.
Your argument that a HTML input field would return a string is invalid, because:
numeric. I doubt someone who thinks casting a form input string to an int is a good idea, really cares whether the data type is truly an “integer”.If you really are keen to support form requests, validate them for what they are with
numeric- and a regex to look for decimal places if you truly want an int.As it stands, people looking to do things “the right way” have to write custom validators which is not right.
I’m a little shocked to find out it’s 2021, the whole world uses JSON payloads, and we don’t have a way to ensure a request contains an actual number, not just a numeric string…? This isn’t just a “type obsession” of a handful of developers. Code that integrates with other systems must have confidence in data types it accepts and possibly forwards to external systems.
As @mattwithoos very eloquently put it, weak typing introduces lots of subtle bugs, especially in conjunction with anything that isn’t PHP!
Can we please have this discussion? Developers need a way to ensure types of JSON request payloads.
I am also shocked that I had to find this post to understand why validation was behaving oddly. I’m with others here who agree this is a discussion we should have. It’s 2021 and even third-party PHP libraries are, more often than not, asking for properly typed data. I get that this was thought out as a comfort feature for people handling forms but it’s time to put that logic to rest. Not to mention that Forms and JSON payloads are only a subset of the use cases. All others would also expect an integer check to only allow ints.
An HTML input field would return an integer in string form, thus why the validator can’t fail on this case.
I’m not sure if a
strictflag would be useful, you can always sanitise your input before passing to the validator.Anyways this is more of a feature request, so we better discuss it on https://github.com/laravel/internals repo.
I was also showed. This is my workaround:
It does make sense to enable a strict mode for validator for your usecase, maybe a flag like
strictwould change the behavior of the validations… Personally I’d refactor my code to work with strings too but I get your point.Ping @themsaid do you think that the validator should cover this usecase?
@m1guelpf
I already made a custom validator for my needs. I’m thinking that the validation rule is misleading. Maybe it should be “form_integer” instead of “integer”.
As for your question: I work with strict data. For example, think to a post request that creates an configuration from a json. That configuration is saved in database. When data is retrieved from database, I expect to have data with correct scalars.
Example:
When i will call the function
getLatestProductthen the type hinting will cause my code to crash. I don’t want to do additional validations on what i got from database, because is supposed to already be correct and validated before accepting it.+1 on the shocked front, it is now 2022 and Laravel 9 appears to function the same way.
Workaround: https://github.com/nwilging/laravel-strict-types-validation
@m1guelpf casts works only for main attributes. In my case
configis an array so is already casted. I am aware that there are a lot of work arounds, i can even make an model class out of theconfigattribute, and use the casts. But this is not my point: you should not be required to do work arounds, when a simple validator can fix a lot of headaches.@m1guelpf I agree, however I am trying to validate an
application/jsonpost.Imho, when I use an validator, I expect to work for any possible cases, not just for
form-data. If this validator is made to validateform-dataposts, then it should be renamed into something more appropriate, like FormDataValidator, or something similar.