Laravel validation messages array indices starting from 0 - php

If in a form request I have rules
[
'items' => ['required', 'array'],
'items.*' => ['required', 'numeric'],
]
Then error message returns like this:
"items.0" => array:1 [
0 => "The selected items.0 is invalid."
]
Is there any way to have the message look like "The selected items #1 is invalid" or something similar, that is actually human readable?
Please note, I need this for the whole system globally, there's already >500 form request classes, although not that many are using array validation, so changing extended class or adding a trait wouldn't be too horrible

Try This,
[
'items' => ['required', 'array'],
'items.*' => ['required', 'numeric'],
],
[
'items.required' => 'Your Message',
]

If you are using custom Request then You can do like this:
public function rules()
{
$rules = [];
foreach ($this->request->get('items') as $key => $value) {
$rules[$key] = 'required';
}
return $rules;
}
Hope This Help you

Related

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",
]);

Request Validation with Laravel 5.3 for Multiple rows

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',
];
}

Laravel 5.2 validation: date_format:Y.m.d not working

I try to validate a POST request.
The format is: d.m.Y (12.1.2017)
My rule is required|date_format:d.m.Y for this field.
I get this error message:
InvalidArgumentException in Carbon.php line 425:
Unexpected data found.
Unexpected data found.
Data missing
If I change the . to - or even / it is working -> POST data changed before to match the rule.
I need the German format for this.
edit:
My validation rules:
public function rules()
{
return [
'title' => 'required|max:255',
'expiration_date' => 'required|date_format:d.m.Y',
//'description' => 'required',
'provision_agent' => 'required|integer|between:0,100',
'discount_consumer' => 'required|integer|between:0,100',
'quota' => 'required|integer',
];
}
Wrap your Format should work i just tried with 5.2 it's working fine.
public function rules()
{
return [
'title' => 'required|max:255',
'expiration_date' => 'required|date_format:"d.m.Y"',
//'description' => 'required',
'provision_agent' => 'required|integer|between:0,100',
'discount_consumer' => 'required|integer|between:0,100',
'quota' => 'required|integer',
];
}
But the error what you added in question InvalidArgumentException in Carbon.php line 425: it seems something else my guess you are using expiration_date some where in controller or model like this with Carbon
echo Carbon::createFromFormat('Y-m-d', '12.1.2017');
You should try something like this
echo Carbon::parse('12.1.2017')->format('Y-m-d')
Wrap your format into quotes:
'date_format:"d.m.Y"'
Try like this,
public function rules()
{
return [
'title' => 'required|max:255',
'expiration_date' => 'date_format:"d.m.Y"|required', // I have changed order of validation
//'description' => 'required',
'provision_agent' => 'required|integer|between:0,100',
'discount_consumer' => 'required|integer|between:0,100',
'quota' => 'required|integer',
];
}
Hope this will solve your problem.
If you don't succeed solving the issue otherwise, you can still use a custom validation rule:
Validator::extend('date_dmY', function ($attribute, $value) {
$format = 'd.m.Y';
$date = DateTime::createFromFormat($format, $value);
return $date && $date->format($format) === $value;
}, 'optional error message');
The extra check $date->format($format) === $value is to avoid erroneously accepting out-of-range dates, e.g. "32.01.2017". See this comment on php.net.
Once the custom validation rule has been defined, you can use it like so:
public function rules() {
return [
'expiration_date' => 'required|date_dmY',
];
}

How to validate array input in laravel?

<input type="text" name="name[2]">
I tried validate like this, but didn't work correctly
$valid = Validator::make($request->all(), [
//'name.2' => 'required',
'name[2]' => 'required',
]);
-- Laravel Framework version 5.3.26
A nice way would be using Form Requests and creating dynamic rules for your arrays, like this
public function rules()
{
$rules = [
'name' => 'required|max:255',
];
foreach($this->request->get('items') as $key => $val)
{
$rules['items.'.$key] = 'required|max:10';
}
return $rules;
}
Here's a nice article talking about this: https://ericlbarnes.com/2015/04/04/laravel-array-validation/
You may also validate each element of an array. For example, to validate that each e-mail in a given array input field is unique, you may do the following:
$validator = Validator::make($request->all(), [
'person.*.email' => 'email|unique:users',
'person.*.first_name' => 'required_with:person.*.last_name',
]);

Categories