Laravel: Validating a number greater than zero is failing
Asked Answered
R

5

27

I gotta validate a price field which needs to be greater than zero (0.01 is valid) so I have the following validation:

$request->validate([
            'product_price' => 'required|numeric|gt:0',
        ]);

The problem is that when I enter a string in the 'product_price' field I'm getting an error:

InvalidArgumentException The values under comparison must be of the same type

why is that? I mean, I'm checking that it should be numeric before even checking that it's > 0

Relator answered 19/9, 2018 at 3:47 Comment(1)
the gt rule is: gt:field, in your cause you gave 0. laravel.com/docs/5.7/validation#rule-gtHorrorstruck
C
78

gt, gte, lt and lte are added in Laravel 5.6 and later versions, I'm guessing that must be the reason for you get the error. (It's working for me though.)

I think you can try like this

$request->validate([
    'product_price' => 'required|numeric|min:0|not_in:0',
]);

min:0 make sure the minimum value is 0 and no negative values are allowed. not_in:0 make sure value cannot be 0. So, combination of both of these rules does the job.

You can define meaningful error messages for certain rule. (You can achieve the same result using regular expressions as well.)

Crotchety answered 19/9, 2018 at 5:37 Comment(7)
Haven’t tried this yet but I believe it won’t work for me as the question clearly states that 0.1 is a valid value and your answer limits the initial value to be >=1Relator
0.1 was an example. Once again, it has to be greater than zero but not need to narrow its starting point to an initial value as 0.1, 0.01, 0.001 ... are all valid valuesRelator
This rule allows all the numbers greater than 0 and less than 10000. Including the decimal numbers like 0.1, 0.001 and etc. Is that what you want ?Crotchety
Sorry, my mistake, didn’t read the answer correctly. One question, is zero allowed in your answer? Because it should not. Sorry for asking, is just that I won’t be able to test it until I get homeRelator
It works like charm! Just got to test it. From all the solutions I've seen online yours is the most direct and cleanest. Thanks youRelator
That's the thing which i wantedMace
Wouldn't doing min:0 to min:1 work ?Sharpedged
G
6

I can see that none of the other answers have addressed the real reason you're getting this error, I'll try and provide some insights and a solution to it.

The problem here is that Laravel is testing all validation rules and not stopping after the first validation error which in your case is numeric (which fails since the value provided is a string), if it did that the error with the gt validator being provided a string value wouldn't be thrown since the validator has already exited after the numeric error.

To have Laravel stop the validation checks after the first failed validation rule, you can prefix your validation rules with the bail validator which basically tells Laravel to stop after the first error.

The resulting code would look like this:

$request->validate([
    'product_price' => 'bail|required|numeric|gt:0',
]);

Note that this solution also makes it so that only a single error is ever returned per field, if in your UI you usually display all the errors for a particular field at a time (instead of only picking the first one from the message bag), this solution would change that.

More information on the bail validation rule can be found here: https://laravel.com/docs/6.x/validation#rule-bail

Glede answered 11/2, 2020 at 14:38 Comment(0)
C
3

For me, this code is working in my project.

$validation_rules = array( 
                'user_id' => 'required|integer|gt:0',
                'type_id' => 'required|integer|gt:0',
            );
$validation = Validator::make($request->all(), $validation_rules);

Here, gt:0 check if the integer is greater than zero.

Hope, this will work for you. If not then please check your Laravel version.

Cutlet answered 28/11, 2019 at 10:32 Comment(0)
A
2

You can try this way ,

Before invoking the Validator::make() function, modify the set of rules by appending the value to compare to like so:

use Illuminate\Support\Facades\Validator;

Validator::extend('greater_than', function ($attribute, $value, $otherValue) {
      return intval($value) > intval($otherValue[0]);
});

$validation = Validator::make($input, ['amount' => 'required|numeric|greater_than:0']);
Argentiferous answered 19/9, 2018 at 4:6 Comment(0)
C
2

For me, this code is working in my project,

use Validator;

 $rules = [
            'product_price' => 'required|gt:0',
        ];

$validator = Validator::make($request->all(), $rules);


if ($validator->fails()) {
  return response()->json(array('status' => false, 'msg' => $validator->errors()->first()));
            exit;
        }
Closing answered 2/6, 2021 at 6:17 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.