I'm using a validator to validate user input in my Laravel 8.5x project.
This is the code I use:
use Illuminate\Support\Facades\Validator;
$validator = Validator::make(['SelectedMonth' => $SelectedMonth, 'SelectedStartDate' => $SelectedStartDate, 'SelectedEndDate' => $SelectedEndDate], [
'SelectedMonth' => 'required|max:7|regex:[^(\d{4}-)?\d{2}$]',
'SelectedStartDate' => 'nullable|max:12|regex:/^\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])$/',
'SelectedEndDate' => 'nullable|max:12|regex:/^\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])$/'
]);
if ($validator->fails()) {
abort(404);
} else {}
It works great but the problem is when the user doesn't set SelectedEndDate or SelectedStartDate to anything and the value stays "0" <- ZERO. The validator doesn't take "0" as nullable so it's always false. How can I add an exception for "0" to be true?
Thanks
Related
I want purchaser_first_name and purchaser_last_name to be required only when the value of gift input in the request is true and the value of authenticated input is false.
What I have tried so far:
public function rules()
{
return [
'gift' => 'required',
'authenticated'=>required,
'purchaser_first_name' => 'required_if:gift,true,required_if:authenticated,false',
'purchaser_last_name' => 'required_if:gift,true,required_if:authenticated,false',
];
}
This approach turns out to use OR operator instead I want the AND operator.
You can try like this:
'purchaser_first_name' => Rule::requiredIf(function () use ($request) {
return $request->input('gift') && !$request->input('authenticated');
}),
In the function, you can set your logic. I'm not sure what you need for real, but it's good for a start.
Also, check docs for more info about that.
Try to change your validation code as below :
return [
'gift' => 'required',
'authenticated'=>'required',
'purchaser_first_name' => 'required_if:gift,true|required_if:authenticated,false',
'purchaser_last_name' => 'required_if:gift,true|required_if:authenticated,false',
];
My form has the same input field multiple times. My form field is as follows:
<input type='text' name='items[]'>
<input type='text' name='items[]'>
<input type='text' name='items[]'>
And request contains ($request['items'):
array:1 [▼
"items" => array:3 [▼
0 => "item one"
1 => "item two"
2 => "item three"
]
]
I want atleast one of the items to be filled. My current validation in the controller is
$validator = Validator::make($request->all(),[
'items.*' => 'required|array|size:1'
]);
It does not work. I tried with combination of size, required, nullable. Nothing works.
In fact, it's enough to use:
$validator = Validator::make($request->all(),[
'items' => 'required|array'
]);
The changes made:
use items instead of items.* - you want to set rule of general items, if you use items.* it means you apply rule to each sent element of array separately
removed size:1 because it would mean you want to have exactly one element sent (and you want at least one). You don't need it at all because you have required rule. You can read documentation for required rule and you can read in there that empty array would case that required rule will fail, so this required rule for array makes that array should have at least 1 element, so you don't need min:1 or size:1 at all
You can check it like this:
$validator = Validator::make($request->all(), [
"items" => "required|array|min:1",
"items.*" => "required|string|distinct|min:1",
]);
In the example above:
"items" must be an array with at least 1 elements.
Values in the "items" array must be distinct (unique) strings, at least 1 characters long.
You can use a custom rule with a closure.
https://laravel.com/docs/5.7/validation#custom-validation-rules
To check if an array has all null values check it with array_filter which returns false if they're all null.
So something like...
$request->validate([
'items' => [
// $attribute = 'items', $value = items array, $fail = error message as string
function($attribute, $value, $fail) {
if (!array_filter($value)) {
$fail($attribute.' is empty.');
}
},
]
]);
This will set the error message: 'items is empty."
Knowing you are using the latest version of Laravel, I really suggest looking into Form Request feature. That way you can decouple validation from your controller keeping it much cleaner.
Anyways as the answer above me suggested, it should be sufficient for you to go with:
'items' => 'required|array'
Just Do it normally as you always do:
$validator = Validator::make($request->all(),[
'items' => 'required'
]);
You should try this:
$validator = $request->validate([
"items" => "required|array|min:3",
"items.*" => "required|string|distinct|min:3",
]);
I am trying to post the following data to an endpoint built up on Laravel.
{
"category": "2",
"title": "my text goes here",
"difficulty": 1,
"correct": {
"id": "NULL",
"text": "Correct"
},
"wrong": [
{
"id": "NULL",
"text": ""
},
{
"id": "NULL",
"text": ""
},
{
"id": "NULL",
"text": ""
}
]
}
and I have the following validation rules.
return [
'correct' => 'required|array',
'correct.text' => 'required',
'wrong' => 'required|array|between:1,3'
];
What I am trying to accomplish is the wrong should be and array and it should contain at least one element and should not exceed 3. Now these rules are satisfying, but there is one more case I need to take care and that is the validation of the text in wrong . With the current rules, if I post the above data, it will accept as there is no rule in place for the text in the wrong section. Which rule I need to add to validate that the wrong section at least contains one entry with a not empty text.
tl;dr
If you have very specific needs for a validator rule, you can always create your own.
Create a Custom Validator
The scheme will be: properties_filled:propertyName:minimumOccurence. This rule will check if the field under validation:
Is an array.
Its elements have at least minimumOccurence amounts of non empty (!== '') values among element properties called propertyName.
In your app/Providers/AppServiceProvider.php file's boot method, you can add the custom rule implementation:
public function boot()
{
Validator::extend('properties_filled', function ($attribute, $value, $parameters, $validator) {
$validatedProperty = $parameters[0];
$minimumOccurrence = $parameters[1];
if (is_array($value)) {
$validElementCount = 0;
$valueCount = count($value);
for ($i = 0; $i < $valueCount; ++$i) {
if ($value[$i][$validatedProperty] !== '') {
++$validElementCount;
}
}
} else {
return false;
}
return $validElementCount >= $minimumOccurrence;
});
}
Then you can use it in your validation like this:
return [
'correct' => 'required|array',
'correct.text' => 'required',
'wrong' => 'required|between:1,3|properties_filled:text,1'
];
Testing
Note: I assumed that you parse your JSON data with json_decode's $assoc parameter set to true. If you use an object then change the $value[$i][$validatedProperty] !== '' in the condition to: $value[$i]->{$validatedProperty} !== ''.
Here is my example test:
$data = json_decode('{"category":"2","title":"mytextgoeshere","difficulty":1,"correct":{"id":"NULL","text":"Correct"},"wrong":[{"id":"NULL","text":""},{"id":"NULL","text":""},{"id":"NULL","text":""}]}', true);
$validator = Validator::make($data, [
'correct' => 'required|array',
'correct.text' => 'required',
'wrong' => 'required|between:1,3|properties_filled:text,1'
]);
$validator->fails();
Take advantage of the validation rule in
EDIT: I assume that wrong will have a specific value, therefore pass that value in this way
return [
'correct' => 'required|array',
'correct.text' => 'required',
'wrong' => 'required|array|between:1,3',
'wrong.text' => 'sometimes|min:1|in:somevalue,someothervalue',
];
The sometimes validation makes sure that field is checked only if exists. To check that there will be at least
I'm not sure, but does min suffice to your request? Otherwise you have to write a custom validation rule as someone else suggested
I got the same issue while trying to validate an array on the API side. I made a solution. try this
$validator = Validator::make($request->all(), [
'target_user_ids' => 'required',
'target_user_ids.*' => 'present|exists:users,uuid|distinct',
]);
if ($validator->fails()) {
return response()->json([
'status' => false,
'error' => $validator->errors()->first(),
], 400);
}
If you want to validate input fields in array, you can define your rules like this:
return [
'correct' => 'required|array',
'correct.text' => 'required',
'wrong' => 'required|array|between:1,3',
'wrong.*.text' => 'required|string|min:1',
];
I'm trying to create a user update validation through form, where I pass, for example 'password'=>NULL, or 'password'=>'newone';
I'm trying to make it validate ONLY if it's passed as not null, and nothing, not even 'sometimes' works :/
I'm trying to validate as :
Validator::make(
['test' => null],
['test' => 'sometimes|required|min:6']
)->validate();
But it fails to validate.
Perhaps you were looking for 'nullable'?
'test'=> 'nullable|min:6'
Though the question is a bit old, this is how you should do it. You dont need to struggle so hard, with so much code, on something this simple.
You need to have both nullable and sometimes on the validation rule, like:
$this->validate($request, [
'username' => 'required|unique:login',
'password' => 'sometimes|nullable|between:8,20'
]);
The above will validate only if the field has some value, and ignore if there is none, or if it passes null. This works well.
Do not pass 'required' on validator
Validate like below
$this->validate($request, [
'username' => 'required|unique:login',
'password' => 'between:8,20'
]);
The above validator will accept password only if they are present but should be between 8 and 20
This is what I did in my use case
case 'update':
$rules = [
'protocol_id' => 'required',
'name' => 'required|max:30|unique:tenant.trackers'.',name,' . $id,
'ip'=>'required',
'imei' => 'max:30|unique:tenant.trackers'.',imei,' . $id,
'simcard_no' => 'between:8,15|unique:tenant.trackers'.',simcard_no,' . $id,
'data_retention_period'=>'required|integer'
];
break;
Here the tracker may or may not have sim card number , if present it will be 8 to 15 characters wrong
Update
if you still want to pass hardcoded 'NULL' value then add the
following in validator
$str='NULL';
$rules = [
password => 'required|not_in:'.$str,
];
I think you are looking for filled.
https://laravel.com/docs/5.4/validation#rule-filled
The relevant validation rules are:
required
sometimes
nullable
All have their uses and they can be checked here:
https://laravel.com/docs/5.8/validation#rule-required
if you want validation to always apply
https://laravel.com/docs/5.8/validation#conditionally-adding-rules
if you want to apply validation rules sometimes
https://laravel.com/docs/5.8/validation#a-note-on-optional-fields
if you want your attribute to allow for null as value too
I'm using Laravel 4.2.8 and trying to validate the next form:
The first select field is required. And only one is required from the next three fields.
Phone with formatting is the last. And another two are for digits (some IDs).
I validate in controller, the code is next:
public function getApplication()
{
$input = Input::except('_token');
Debugbar::info($input);
$input['phone'] = preg_replace('/[^0-9]/', '', $input['phone']); // remove format from phone
$input = array_map('intval', $input); // convert all numeric data to int
Debugbar::info($input);
$rules = [ // Validation rules
['operation-location' => 'required|numeric'],
['app-id' => 'numeric|min:1|required_without_all:card-id,phone'],
['card-id' => 'numeric|digits:16|required_without_all:app-id,phone'],
['phone' => 'numeric|digits:12|required_without_all:app-id,card-id']
];
$validator = Validator::make($input, $rules);
if ($validator->passes()) {
Debugbar::info('Validation OK');
return Redirect::route('appl.journal', ['by' => 'application']);
}
else { // Validation FAIL
Debugbar::info('Validation error');
// Redirect to form with error
return Redirect::route('appl.journal', ['by' => 'application'])
->withErrors($validator)
->withInput();
}
}
As you may see I convert numeric IDs to integers myself and leave only number for phone number.
The problem is when I submit form as it is, it passes validation, despite one field is required and starter phone format is too short.
I've tried changing required_without_all to just required on all fields (!), but it still passes fine with blank empty form submitted.
And I expect at least one field to be properly filled.
Debug of my inputs.
Initial:
array(4) [
'operation-location' => string (1) "0"
'app-id' => string (0) ""
'card-id' => string (0) ""
'phone' => string (6) "+3 8(0"
]
After conversion to int:
array(4) [
'operation-location' => integer 0
'app-id' => integer 0
'card-id' => integer 0
'phone' => integer 380
]
Posted similar smaller problem to Laravel issues.
I know this sounds weird but I think this is just an issue with your rules array.
You current rules array is an array of arrays. The Validator looks for an array with keys and values. I believe your current rules are being parsed as keys, but with no value. And then the Validator was basically seeing no rules, and it automatically passed. Try this.
$rules = [
'operation-location' => 'required|numeric',
'app-id' => 'numeric|min:1|required_without_all:card-id,phone',
'card-id' => 'numeric|digits:16|required_without_all:app-id,phone',
'phone' => 'numeric|digits:12|required_without_all:app-id,card-id'
];