Laravel form input integer length - php

In Laravel form input validation, you can specify a minimum and a maximum length of a given input field.
$inputRules = [
'postCode' => 'min:3|max:8'
];
Validation outcome
'BA45TZ' = true
'FF' = false
'GH22 55XYZ' = false
However if I do the same for a number, it will validate whether the input is less than or greater than the input, then return on that.
$inputRules = [
'cv2' => 'min:3|max:4'
];
Validation outcome
'586' = false
'4' = true
'2' = false
'3' = true
I actually want to validate a numbers length not it's numerical value. I can't figure out how to do this. Google has been no help, or I am not searching the right thing.
Anybody had any experience with this?
EDIT: I have answered my own question. I had missed Laravels digits_between.

Like an idiot, I missed Laravels digits_between validator rule. I swear I had scoured those rules, but here we are.
Thank you everyone for your help.
$inputRules = [
'cv2' => 'required|numeric|digits_between:3,4'
];

That's the expected behavior of Laravel's size, min and max validations. You can't change it.
For string data, value corresponds to the number of characters. For numeric data, value corresponds to a given integer value. For files, size corresponds to the file size in kilobytes.
To solve this you have to create a custom validation rule.
Something like this:
Validator::extend('min_length', function($attribute, $value, $parameters){
return strlen($value) >= $parameters[0];
});
Validator::extend('max_length', function($attribute, $value, $parameters){
return strlen($value) <= $parameters[0];
});
And you can use them in the same way:
'cv2' => 'min_length:3|max_length:4'

For length in number you've to use size, but you can't put ranges in it. So, the best thing to do is making a custom validation.
Here is the documentation in laravel: http://laravel.com/docs/5.0/validation#custom-validation-rules
And an example:
Validator::extend('minsize', function($attribute, $value, $parameters)
{
return strlen($value) >= $parameters[0];
});
And do the same with maxsize.

Related

Laravel validator compare one value to another only if both are present

I'm using Laravel version v8.29.0
I am using the Laravel validator to validate values passed in from an HTTP request. In the request, I have an array of objects, each object has a min and a max value.
Right now I have this validation in place to make sure that the min value is less than the max value as well as that the max value is greater than the min value:
$this->validate($request, [
'someObject.*.someOtherObject.yetAnotherObject.min' => 'nullable|numeric|lte:someObject.*.someOtherObject.yetAnotherObject.max',
'someObject.*.someOtherObject.yetAnotherObject.max' => 'nullable|numeric|gte:someObject.*.someOtherObject.yetAnotherObject.min',
]);
This works just fine if both values are passed in, but for my application it is allowed for just one or the other or neither to be passed in.
If I only pass in the max value then I get an error message that says the max value needs to be greater than the min value even though the min value was not passed in.
Same thing for the min value, if I only pass in the min value then I get an error message that says the min value must be less than the max value.
My question is what syntax changes do I need to make to the code above to allow one or the other, neither or both values for min and max to be passed in and only validate the min and max in regards to each other if they are both passed in?
I don't think there's a built in way to conditionally use the lte and gte depending on if the other value is present.
What you could do is use the array syntax and a Closure instead:
$this->validate($request, [
'someObject.*.someOtherObject.yetAnotherObject.min' => [
'nullable',
'numeric',
function ($attribute, $value, $fail) use ($request) {
$max = $request->input(str_replace('min', 'max', $attribute));
if (isset($value, $max) && $value > $max) {
$fail(__('validation.lte.numeric', ['value' => $max]));
}
},
],
'someObject.*.someOtherObject.yetAnotherObject.max' => [
'nullable',
'numeric',
function ($attribute, $value, $fail) use ($request) {
$min = $request->input(str_replace('max', 'min', $attribute));
if (isset($value, $min) && $value < $min) {
$fail(__('validation.gte.numeric', ['value' => $min]));
}
},
],
]);
In the above, I'm also using __() (translate) helper function to get the default error message that Laravel would have returned.

Laravel: Using validator's sometimes method when input is an array

I have a form that posts a structure field as an array. The structure array contains definitions of database table columns.
$validator = Validator::make($request->all(), [
'structure' => 'required|array|min:1',
'structure.*.name' => 'required|regex:/^[a-z]+[a-z0-9_]+$/',
'structure.*.type' => 'required|in:integer,decimal,string,text,date,datetime',
'structure.*.length' => 'nullable|numeric|required_if:structure.*.type,decimal',
'structure.*.default' => '',
'structure.*.index' => 'required_if:is_auto_increment,false|boolean',
'structure.*.is_nullable' => 'required_if:is_auto_increment,false|boolean',
'structure.*.is_primary' => 'required_if:is_auto_increment,false|boolean',
'structure.*.is_auto_increment' => 'required_if:structure.type,integer|boolean',
'structure.*.is_unique' => 'required_if:is_auto_increment,false|boolean',
'structure.*.decimal' => 'nullable|numeric|required_if:structure.*.type,decimal|lt:structure.*.length',
]);
Without going into explanation of all the rules, one thing should be made sure that the length field is always null when the type is not string or decimal as you cannot assign a length to columns other than these types. So, I am trying to use the sometimes method on the $validator instance.
$validator->sometimes('structure.*.length', 'in:null', function ($input) {
// how to access the structure type here?
});
My question is inside the closure, how do I make sure that the length is null only for the array element that has the type set to other than string or decimal.
I have tried the dd function and it seems the whole input array is passed to the closure.
$validator->sometimes('structure.*.length', 'in:null', function ($input) {
dd($input);
});
Here is the output of the dd method.
I can use a foreach construct but wouldn't that be inefficient? Checking all the elements for a single element?
How do I check the type only for the array element under consideration?
Is there a Laravel way to do this?
How about thinking opposite? if the Type is String or Decimal, the Length field will become Required.
$validator->sometimes('structure.*.length', 'required', function ($input) {
return $input->type == 'string' or $input->type == 'decimal';
});
This is a great question. I took a look at the API for sometimes(). It seems, what you want to do, is currently not possible with it.
A possible alternative could be to use an After Validation Hook. For example:
$validator->after(function ($validator) {
$attributes = $validator->getData()['structure'];
foreach($attributes as $key => $value) {
if(! in_array($value['type'], ['string', 'decimal']) && ! is_null($value['length'])) {
$validator->errors()->add("structure.{$key}.length", 'Should be null');
}
}
});

Laravel required_if does not accept other parameters

I have some problems with Laravel's validation. I'm using required_if validator.
What I want to achieve: When the hilightColorBool is true the hilightColor should be required, should be integer between min:1 and max:5.
...
'hilightColorBool' => 'required|boolean',
'hilightColor' => 'required_if:hilightColorBool,1|integer|min:1|max:5'
...
But when I'm doing it like above it always returns that hilghtColor is bool, when I do remove the integer, min and max from hilightColor it works good, but I need to validate anyway if it is integer between 1 and 5. It seems weird to me.
Going on from my comment, i may do it like this:
$rules = [
'hilightColorBool' => 'required|boolean',
];
if (is_bool($request->get('hilightColorBool'))) {
$rules['hilightColor'] = 'required|integer|min:1|max:5';
}
then simply do:
$request->validate($rules);

Laravel validate int or float numbers as string

in my project. all mount maybe int or float or was even double.in database amount column type is varchar and for each choose amount by user i have simple limitation, for example amount must be more than some value and less that some value. but i get error validation in laravel.
$ps = DB::table('merchant_web_service')->whereCustomerKey($request->input('customer_key'))->first();
/* $ps->minimum_range_buy is 5 and $ps->maximum_range_buy is 10*/
$validate_amount = Validator::make($request->all(),
['amount' => "required|min:$ps->minimum_range_buy|max:$ps->maximum_range_buy"]);
validator error is:
"The amount must be at least 10 characters."
my test amount values: 1000,100.1
Since you didn't specify any rule for the input data type, it validates it as a string. Try numeric and between rules.
$validate_amount = Validator::make($request->all(),
['amount'=>
"required|numeric|between:$ps->minimum_range_buy,$ps->maximum_range_buy"
]);
try this
$rules = [
'your_field' => 'required|regex:/^\d*(\.\d{2})?$/'
]

Using system date in Laravel input validation

I am trying to create a few validation rules for an input form using Laravel 4.x and I have also go the Validator service from Laracasts.
Is there any way to use the current year, taken from the system date, and use that in the rules?
For example, I want to create a rule that says that the year entered in the input form does not exceed the current year (i.e : I cannot put in 2015 or any higher year as of this day)
You could do this:
'date' => array('min:'.date('Y'), 'max:'.date('Y'), 'date_format:"Y"');
Something along that line.. Catch my drift though right?
Note: This is untested.
PS: If for arguments sake you have a different format than just the year, you could split the inputs just for the validation.
$input = Input::only('date');
$input['date-year'] = date('Y', strtotime($input['date']));
//And then the validation rule will look something like this...
$rules['date-year'] = array('min:'.date('Y'), 'max:'.date('Y'), 'date_format:"Y"');
Hope that helped.
You can create new validation rule like this:
// Less than equal
Validator::extend('lte', function($attribute, $value, $parameters)
{
if ( (float) $value <= (float) $parameters[0] )
return true;
});
Use the new rule
$input = array('year' => 2015);
$rules = array('year' => 'lte:'.date('Y'));
$validation = Validator::make($input, $rules);

Categories