Laravel validating that key in array is in an array of given strings - laravel

I'm building an API that takes in an array of 'additional_data' but I want some control over the fields that can be passed in.
Take the following JSON:
{
"name": "Joe Bloggs",
"additional_data": {
"type": "example",
"other_type": "example"
}
}
My current validation attempt:
return [
'name' => ['required'],
'additional_data.*' => ['sometimes', Rule::in(['type'])]
];
This always fails validation, what I'm looking for is to validate the key of the array so I can make sure the keys passed in are part of a 'whitelist'.

What you do now is you try to validate content of additional_data.type and additional_data.other_type.
You can do this by adding a custom validator. For example
Validator::extend('check_additional_data_keys', function($attribute, $value, $parameters, $validator) {
return is_array($value) && array_diff(array_keys($value), ['type', 'other_type']) === 0);
});
and use it inside your current rules
return [
'name' => ['required'],
'additional_data' => ['check_additional_data_keys'],
'additional_data.*' => ['required', 'string'],
];

Just specify your whitelist keys using the array validation rule:
return [
'name' => 'required',
'additional_data' => [
'sometimes',
'array:type',
],
];

1- In case you want applay same validation on all arrays' keys you can use the following:
return [
'name' => 'required',
'additional_data' => ['array', Rule::in(['type'])]
];
2- In case each key in the array needs different validation use the following:
return [
'name' => 'required',
'additional_data' => 'array',
'additional_data.ky1' => ['your validation here'],
'additional_data.ky2' => ['your validation here'],
];

Related

How can I validate my request where the data is in a nested structure?

My controller receives the following XHR request:
[
"data" => [
"key1" => "value1",
"key2" => "value2",
]
]
That's why the validation always returns a fail. But I only want to validate the data within data. Is there a request validation function where I only pass the data?
As a user mentioned in the comments, you have to iterate each entry by using data.KEY format.
If your data is like:
[
"data" => [
"key1" => "value1",
"key2" => "value2",
]
]
You can validate it like this:
public function rules()
{
return [
'data' => ['required', 'array'],
'data.key1' => ['required', 'string', 'in:value1,valueN'],
'data.key2' => ['required', 'string', 'unique:table,column'],
];
}
Those rules are just examples, so please, do read How to validate arrays as the documentation has a defined section about it.
As Tim Lewis correctly mentioned, if all the keys have the same rules, then you can use one single rule and use data.*:
public function rules()
{
return [
'data' => ['required', 'array'],
'data.*' => ['required', 'string', 'in:value1,valueN'],
];
}
I assume your controller receives data i.e.
public function functionName(Request $request){
$request->validate([
'key1' => 'required|integer|min:0',
'key2' => 'required'
]);
}

Multiple inputs in one validation rule

return [
'contract_code' => 'required',
'name' => 'required|string',
'abbreviation' => 'required|string',
'linecount_divisor' => 'required|integer'
];
// into input fields => 'required'
How to shorten the validation rule in multiple inputs?
if You have the same validation rule for multiple and you want to shorten your code just use form requests.
php artisan make:request RequestName
And then in the controller Functions use it
public function save(RequestName $requestName)
{
}
don't forget to use that request class.
use App\Http\Requests\RequestName;
Here is a solution assuming all input fields need to have a common rule like required.
$rules = array_map(function($curr) { return [$curr => 'required']; }, array_keys(request()->all()));
Try this one in Laravel
$validation=array();
$validation= [
'contract_code' => 'required',
'name' => 'required|string',
'abbreviation' => 'required|string',
'linecount_divisor' => 'required|integer'
];
$this->validate($request,$validation);

How to validate array in Request rules laravel?

I create request in laravel for validation where i have to validate phone number array.How to validate it. Below i am sharing:
Array that i pass in postman is:
{
"name": "test nbame",
"phone_number": {
"number": "+8896 5432",
"internationalNumber": "+852 7896 5432",
"nationalNumber": "+8896 5432",
"e164Number": "+85278965432",
"countryCode": "HK",
"dialCode": "+852"
},
"designation": "xyz"
}
public function rules()
{
return [
'name' => 'required',
'dial_number' => 'required',
'phone_number' => 'required|regex:/(^[0-9 ]+$)+/',
//'image' => 'required',
];
}
how to validate phone_number array.
Based on your json you can do something like below
public function rules()
{
return [
'name' => 'required',
'dial_number' => 'required',
'phone_number' => 'required|array',
'phone_number.number' => 'required|regex:/(^[0-9 ]+$)+/',
'phone_number.internationalNumber' => 'required|regex:/(^[0-9 ]+$)+/',
'phone_number.nationalNumber' => 'required|regex:/(^[0-9 ]+$)+/',
'phone_number.e164Number' => 'required',
'phone_number.countryCode' => 'required|string',
'phone_number.countryCode' => 'required|string',
'phone_number.dialCode' => 'required',
//'image' => 'required',
];
}
for more info you can visit laravel documentation
You're validating against a nested array in Laravel:
public function rules()
{
return [
...
'phone_number.number' => 'required|regex:/(^[0-9 ]+$)+/',
];
}
Read more in the docs.
You will check the number by regex. You will find a lot of variants of possible phone numbers. That means that you need a regex which is very flexible. How flexible the regex should be depends on you. here is an example:
'phone_number.number' => 'required|regex:/(^[0-9 ]+$)+/',

Laravel one validation function for Store and Update

I am trying to have one validation function for both store and update. So I don't repeat code. It works well. The problem is testing 'unique'. I worked around with this idea. But feels long-winded. Is there a better way to do it?
I want to check for unique at the store.
At update, unique check ignores own id.
I don't want different validations like I did as the user will be
first notified of the unique error, he will fix it. then something
else might be wrong and he has to fix again.
.
public function validateRequest($request){
if($request->method() == "PUT")
{
$val = $this->validate($request, [
'name' => 'unique:customers,id',
'phone' => 'unique:customers,id',
]);
}
if($request->method() == "POST"){
$val = $this->validate($request, [
'name' => 'unique:customers',
'phone' => 'unique:customers'
]);
}
$validation = $this->validate($request, [
'name' => 'required',
'phone' => 'required|integer|gt:0',
'phone2' => 'nullable|integer|gt:0|',
'email' => 'email|nullable',
'note' => 'nullable',
],
[
'phone.integer' => "Invalid phone format. Use international format. Eg: 971550000000",
'phone2.integer' => "Invalid phone format. Use international format. Eg: 971550000000",
'required' => "Required Field",
]);
return $validation;
}

Laravel Validation amount array of fields not work

I have created rule validation as follow :
$rules = [
'items.*.qty' => ['required', 'integer', 'min:1'],
'items.*.ordered_qty' => ['required','numeric','min:1']
]
$this->validate($request, $rules);
here i need to validate that each ordered_qty should be greater than qty I have tried the below way but it doesn't work for me
$rules = [
'items.*.qty' => ['required', 'integer', 'min:1','max:items.*.ordered_qty'],
'items.*.ordered_qty' => ['required','numeric','min:1']
]
$this->validate($request, $rules);
i tried custom validation also but i could not able to getting the value of other field
$rules = [
'items.*.qty' => ['required', 'integer', 'min:1',function ($attribute, $value, $fail) {
if ($value > ordered_qty) {
$fail(':attribute qty is invalid!');
}
}],
'items.*.ordered_qty' => ['required','numeric','min:1']
]
It validate wrong. How can i do the comparision on array of objects among their attributes
You are using the max on qty but max suspect a value while you are trying to validate it with the input of another field. I think you need to use lte, see: https://laravel.com/docs/5.8/validation#rule-lte

Resources