Request Validation with Laravel 5.3 for Multiple rows - php

My Request File rules are
public function rules()
{
return [
'mobile' => 'required',
'code' => 'required',
];
}
My input data can be a simple => for which the request validation is working fine.
{
"mobile":"81452569",
"code":"4858"
}
My input data can be a complex too => for which the request validation is not working fine.
[{
"mobile":"81452569",
"code":"4858"
},
{
"mobile":"81452570",
"code":"4858"
}]
How to validate for multiple rows with request.

I would sent it all in array to the request object like so:
"data" => [
[
"mobile" => "81452569",
"code" => "4858"
],
[
"mobile" =>"81452570",
"code" =>"4858"
]
];
Then in your validation rules do this:
public function rules()
{
return [
'data.*.mobile' => 'required',
'data.*.code' => 'required',
];
}

Related

Laravel: Is it possible to apply different form validation rules to objects in an array

I have a Laravel 9 API.
I am posting the following json to an endpoint.
{
"shapes": [
{
"type": "Point",
"coordinates": [1, 2]
},
{
"type": "MultiPolygon",
"coordinates": [
[
[
[1, 2],
[3, 4],
[5, 6],
]
]
]
}
]
}
I have some form validation (in a form request class) that needs to validate the coordinates given differently based on the type.
I.e. Apply the PointCoordinatesValidator rule if the shape's type is Point or apply the MultiPolygonCoordinatesValidator rule if the shape's type is MultiPolygon.
public function rules()
{
return [
'shapes' => 'required|array|min:1',
'shapes.*.type' => [
'required',
'string',
'in:Point,MultiPolygon',
],
'shapes.*.coordinates' => [
'required',
request()->input('shapes.*.type') == 'Point' ?
new PointCoordinatesValidator :
new MultiPolygonCoordinatesValidator,
],
];
}
However, when running this, the custom MultiPolygonCoordinatesValidator rule is being applied to both shapes, not just the shape where it's type == MultiPolygon.
I can see that
request()->input('shapes.*.type') is Point for shapes.0 and MultiPolygon for shapes.1
Am I expecting too much from the validation? Is it possible to validate the different items in the array differently based on a value in that array?
Just pass the array element in and then implement the type check in your rule:
'shapes.*' => [
'required',
new CoordinatesValidator(),
],
Then, in the rule, the $value will contain the type and the coordinates.
It definitely is possible, but not by checking request()->input('shapes.*.type') == 'Point'; that * is a wildcard, and isn't really checked on each iteration.
You can construct the rules from the input, but it's a bit of an anti-pattern, and might have issues if type is null, or similar.
Give this a shot:
public function rules() {
$rules = [
'shapes' => 'required|array|min:1',
'shapes.*.type' => [
'required',
'string',
'in:Point,MultiPolygon',
]
];
foreach(request()->input('shapes', []) as $index => $shape) {
$rules["shapes.{$index}.coordinates"] = [
'required',
$shape['type'] == 'Point' ? new PointCoordinatesValidator() : new MultiPolygonCoordinatesValidator()
];
}
return $rules;
}
Using that, you'll get something like this:
[
'shapes' => 'required|array|min:1',
'shapes.*.type' => [
'required',
'string',
'in:Point,MultiPolygon'
],
'shapes.0.coordinates' => [
'required',
new PointCoordinatesValidator()
],
'shapes.1.coordinates' => [
'required',
new MultiPolygonCoordinatesValidator()
]
// And so on...
]
Your $rules array can get pretty large, depending on the number of shapes being uploaded, but this should allow you to explicitly target certain validation rules for each shape, depending on the type supplied.

How to add required if validation rule if a file has been uploaded

I'm working with Laravel 5.8 and here is my validation request form:
public function rules()
{
return [
'art_audio_file' => ['nullable', 'file', 'mimes:audio/mpeg,mpga,mp3,wav,aac'],
'art_audio_file_title' => ['required_if: IF USER HAS UPLOADED FILE']
];
}
I wonder, how can I make art_audio_file_title required if art_audio_file is not empty.
So how can I do that?
You can add your logic like below:
return [
'art_audio_file' => ['nullable', 'file', 'mimes:audio/mpeg,mpga,mp3,wav,aac'],
'art_audio_file_title' => [
Rule::requiredIf(function() {
return !empty($this->request->get('art_audio_file'));
})
]
];
or in your case simply:
'art_audio_file_title'=>'required_with:art_audio_file'

Custom validation messages in Laravel

I am facing the problem with custom validation messages in laravel.
I want to validate user create request, I have data as follows:
first_name:Akhsay
middle_name:R
last_name:Doe
gender:male
miscellaneous:{"dob":"","birth_name":"xyz"}
I have created the validation rules for creating a user in userCreateRequest.php as
public function rules()
{
return [
'first_name' => 'required',
'middle_name' => 'required',
'last_name' => 'required',
'gender' => 'required',
'miscellaneous' => 'json|validate_misc_info',
];
}
/**
* validation messages
*
* #return array
*/
public function messages()
{
return [
"first_name.required" => "First name is required.",
"middle_name.required" => "Middle name is required.",
"last_name.required" => "Last name is required.",
"gender.required" => "Gender is required.",
'miscellaneous.validate_misc_info' => '(**want to show specific error message here**)?'
];
}
For miscellaneous information, I have created a custom validation service provider and in boot method of custom validator I have written the validation code as
Validator::extend('validate_misc_info',function($attribute, $value, $params, $validator) {
$data = json_decode($value, true);
$rules = [
"dob" => "required|date",
"birth_name" => "required|min:2|max:50",
];
$messages= [
"dob.required" => "Date of birth is required",
"birth_name.required" => "Birth name is required",
];
$validator = $data ? Validator::make($data, $rules, $messages) : false;
if ($validator && $validator->fails()) {
return false;
}
return true;
});
But when I 'm using this validation rule in userCreateRequest.php as
public function rules()
{
return [
'first_name' => 'required',
'middle_name' => 'required',
'last_name' => 'required',
'initial' => 'required',
**'miscellaneous' => 'json|validate_misc_info',**
];
}
Its showing me the error as
{
"message": "The given data was invalid.",
"errors": {
"miscellaneous": [
"validation.validate_misc_info"
]
}
but I want to show a specific error message as
{
"message": "The given data was invalid.",
"errors": {
"miscellaneous": [
"Date of birth is required"
]
}
Please help me.

Laravel array validation in Form Request

I can't validate a field, which contains array elements, in Form Request class.
Rules method:
public function rules()
{
return [
"state" => 'required',
"state.0" => 'required',
"state.*" => 'required',
];
}
There is an array in request->all()
"state" => array:1 [
0 => ""
]
Zero element is empty. But validation is successful.
What am I doing wrong?
In order to handle the dynamic fields, you will need to loop through all the posted "items" and add a rule for each.
Here is an updated method demonstrating this:
public function rules() {
$rules = [
'state' => 'required',
];
foreach($this->request->get('state') as $key => $val) {
$rules['state.'.$key] = 'required';
}
return $rules;
}

How to validate array in Laravel?

I try to validate array POST in Laravel:
$validator = Validator::make($request->all(), [
"name.*" => 'required|distinct|min:3',
"amount.*" => 'required|integer|min:1',
"description.*" => "required|string"
]);
I send empty POST and get this if ($validator->fails()) {} as False. It means that validation is true, but it is not.
How to validate array in Laravel? When I submit a form with input name="name[]"
Asterisk symbol (*) is used to check values in the array, not the array itself.
$validator = Validator::make($request->all(), [
"names" => "required|array|min:3",
"names.*" => "required|string|distinct|min:3",
]);
In the example above:
"names" must be an array with at least 3 elements,
values in the "names" array must be distinct (unique) strings, at least 3 characters long.
EDIT: Since Laravel 5.5 you can call validate() method directly on Request object like so:
$data = $request->validate([
"name" => "required|array|min:3",
"name.*" => "required|string|distinct|min:3",
]);
I have this array as my request data from a HTML+Vue.js data grid/table:
[0] => Array
(
[item_id] => 1
[item_no] => 3123
[size] => 3e
)
[1] => Array
(
[item_id] => 2
[item_no] => 7688
[size] => 5b
)
And use this to validate which works properly:
$this->validate($request, [
'*.item_id' => 'required|integer',
'*.item_no' => 'required|integer',
'*.size' => 'required|max:191',
]);
The recommended way to write validation and authorization logic is to put that logic in separate request classes. This way your controller code will remain clean.
You can create a request class by executing php artisan make:request SomeRequest.
In each request class's rules() method define your validation rules:
//SomeRequest.php
public function rules()
{
return [
"name" => [
'required',
'array', // input must be an array
'min:3' // there must be three members in the array
],
"name.*" => [
'required',
'string', // input must be of type string
'distinct', // members of the array must be unique
'min:3' // each string must have min 3 chars
]
];
}
In your controller write your route function like this:
// SomeController.php
public function store(SomeRequest $request)
{
// Request is already validated before reaching this point.
// Your controller logic goes here.
}
public function update(SomeRequest $request)
{
// It isn't uncommon for the same validation to be required
// in multiple places in the same controller. A request class
// can be beneficial in this way.
}
Each request class comes with pre- and post-validation hooks/methods which can be customized based on business logic and special cases in order to modify the normal behavior of request class.
You may create parent request classes for similar types of requests (e.g. web and api) requests and then encapsulate some common request logic in these parent classes.
Little bit more complex data, mix of #Laran's and #Nisal Gunawardana's answers
[
{
"foodItemsList":[
{
"id":7,
"price":240,
"quantity":1
},
{
"id":8,
"quantity":1
}],
"price":340,
"customer_id":1
},
{
"foodItemsList":[
{
"id":7,
"quantity":1
},
{
"id":8,
"quantity":1
}],
"customer_id":2
}
]
The validation rule will be
return [
'*.customer_id' => 'required|numeric|exists:customers,id',
'*.foodItemsList.*.id' => 'required|exists:food_items,id',
'*.foodItemsList.*.quantity' => 'required|numeric',
];
You have to loop over the input array and add rules for each input as described here: Loop Over Rules
Here is a some code for ya:
$input = Request::all();
$rules = [];
foreach($input['name'] as $key => $val)
{
$rules['name.'.$key] = 'required|distinct|min:3';
}
$rules['amount'] = 'required|integer|min:1';
$rules['description'] = 'required|string';
$validator = Validator::make($input, $rules);
//Now check validation:
if ($validator->fails())
{
/* do something */
}
The below code working for me on array coming from ajax call .
$form = $request->input('form');
$rules = array(
'facebook_account' => 'url',
'youtube_account' => 'url',
'twitter_account' => 'url',
'instagram_account' => 'url',
'snapchat_account' => 'url',
'website' => 'url',
);
$validation = Validator::make($form, $rules);
if ($validation->fails()) {
return Response::make(['error' => $validation->errors()], 400);
}
In my Case it works fine
$validator = Validator::make($request->all(), [
"names" => "required|array|min:3",
"*.names"=> "required|string|distinct|min:3",
]);

Categories