Validating a JSON array in Laravel - php

I have a controller which receives a following POST request:
{
"_token": "csrf token omitted",
"order": [1,2,3,4,5,6,7,8]
}
How can I use validators to ensure that elements in order are unique, and between 1 and 7? I have tried the following:
$this->validate($request, [
'order' => 'required|array',
'order.*' => 'unique|integer|between:1,7'
]);
The first clause is checked, the secound one passes even when the input is invalid.

Using distinct rule:
distinct
When working with arrays, the field under validation must not have any
duplicate values.
In your case, it could look like this:
$this->validate($request, [
'order' => 'required|array',
'order.*' => 'distinct|integer|between:1,7'
]);

The unique validator keyword is for checking a value's duplicates in database.
You should use custom validator for such situations.
See: https://laravel.com/docs/5.1/validation#custom-validation-rules

Related

Using excludes_unless validation rule with arrays in Laravel

Laravel's exclude_unless,field,value rule doesn't seem to work in the instance where field is an array of values and value is contained within the field array.
Given the following:
$validator = Validator::make($request->all(), [
'some_array' => 'array',
'some_field' => 'exclude_unless:some_array,foo|alpha_num',
]);
Where some_array is equal to ['foo'], the validator will fail to exclude some_field. This seems to be because the comparison that lies beneath excludes_unless is in_array(['foo'], ['foo']) which returns false.
Is it possible to achieve the same logic of exclude_unless — excluding a field from validation if another field equals a certain value, but where the field being compared against is an array and we're checking that the value is in that array?
As long as you're using Laravel 8.55 or above, you could use Rule::when():
use Illuminate\Validation\Rule;
$someArray = $request->input('some_array', []);
$validator = Validator::make($request->all(), [
'some_array' => 'array',
'some_field' => Rule::when(!empty(array_intersect(['foo'], $someArray)), ['exclude']),
]);

Laravel 8 unique validation rule doesn't work with user_id

I'm using Laravel 8 and the unique validation rule to ensure that a record remains unique, I'm now trying to extend this so that it's unique per user as well, but when expanding the functionality and using the rule in array form it doesn't seem to validate the user ID and instead gives me a integrity constraint violation.
So I have a table called brands, and this table contains two columns in question: brand and user_id, I need to ensure that when storing a record that the brand is unique against the brand column and that the logged in in user's ID the one making the request, e.g:
Two users can have the same brand, but a single user can't have multiples of the same brand.
$validator = Validator::make($request->all(), [
'brand' => [
'required',
'string',
Rule::unique('brands')->where(function ($query) {
return $query->where('user_id', Auth::id());
})
],
'url' => 'required|string',
'telephone' => 'required|string|min:11|max:11'
]);
I've also tried:
'brand' => 'required|string|unique:brands,brand,user_id,' . Auth::id()
What am I missing?
According to the documentation you have to use the ignore() function:
Rule::unique('users')->ignore($user->id),
on your case:
Rule::unique('brands')->ignore($user->id, 'user_id'),

How to make Laravel unique validation work on an input array?

UpdateEntityRequest.php:
'phones' => 'sometimes|nullable|array',
'phones.*.id' => 'sometimes|required|integer|distinct|exists:entity_phones,id,entity_id,'.$this->id,
'phones.*.number' => 'required|alpha_num|max:255|distinct|unique:entity_phones,number,'.$this->id.',entity_id',
entity_phones table:
id, number, entity_id.
unique constraint: (number, entity_id)
EntityRepository.php:
foreach ($attributes['phones'] as $phone) {
if (isset($phone['id'])) {
$entity->phones()->updateOrCreate([
'id' => $phone['id'],
'entity_id' => $entity->id
], $phone);
} else {
$entity->phones()->create($phone);
}
}
My entity can have more than phone associated, but not a repeated number. My intention is to check the unique (entity_id, number) in the UpdateEntityRequest.php so:
If the phone object comes without an id, it should check that the combination of number, entity_id doesn't exists. But the number can exist with other entity_id.
If the request comes with an id, it should check that the combination of number, entity_id doesn't exists only in other ids, but ignore the given id.
I'm having trouble witht the Laravel Unique rule validating only when i want it to make the validation. Any ideas how could I make this solution would be appreciated.
If you need to ignore a given ID during the unique check try using the Rule class to fluently define the rule.
use Illuminate\Validation\Rule;
Validator::make($request_data, [
'number' => [
'required',
'alpha_num', (...all your other rules)
Rule::unique('entity_phones')->ignore($entity_id),
],
]);
You can read more in laravel docs about unique rule in paragraph: Forcing A Unique Rule To Ignore A Given ID.
I ended up doing this:
$phoneIds = $this->input('phones.*.id');
'phones.*.number' =>
[
'required_with:phones',
'alpha_num',
'max:255',
'distinct',
Rule::unique('entity_phones', 'number')
->where('entity_id', $this->id)
->where(function ($query) use ($phoneIds) {
return $query->where('id', '!=', array_shift($phoneIds));
})
],

Laravel validation rules - optional, but validated if present

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

Laravel 5.2 validator: Validate Array request parameter, at least one value must be selected

I am having a form where i am having title, body, answers[][answer] and options[][option].
I want atleast one answer must be selected for the given question, for example:
i have ABC question and having 5 options for that question,now atleast one answer must be checked or all for given question.
Efforts
protected $rules = [
'title' => 'required|unique:contents|max:255',
'body' => 'required|min:10',
'type' => 'required',
'belongsto' => 'sometimes|required',
'options.*.option' => 'required|max:100',
'answers.*.answer' => 'required',
];
But this is not working. i want atleast one answer must be selected.
Please help me.
The problem is that on $_POST an array filled with empty strings will be passed if no answer is selected.
$answers[0][0] = ''
$answers[0][1] = ''
$answers[0][2] = ''
Hence the following will not work since array count will be greater than zero due to the empty strings:
$validator = Validator::make($request->all(), [
'answers.*' => 'required'
]);
The easiest way to solve this is to create a custom Validator rule by using Laravel's Validator::extend function.
Validator::extendImplicit('arrayRequireMin', function($attribute, $values, $parameters)
{
$countFilled = count(array_filter($values));
return ($countFilled >= $parameters[0]);
});
And then call it in your Validation request:
$validator = Validator::make($request->all(), [
'answers.*' => 'arrayRequireMin:1'
]);
The magic happens in array_filter() which removes all empty attributes from the array. Now you can set any minimum number of answers required.
Validator::extendImplicit() vs Validator::extend()
For a rule to run even when an attribute is empty, the rule must imply that the attribute is required. To create such an "implicit" extension, use the Validator::extendImplicit() method:
Laravel's validation docs
Try this,
'answer.0' => 'required'
it will help you. I think.

Categories