How to validate array in Laravel? - php

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

Related

How do I get ONLY the validated data from a laravel FormRequest?

Lets say I have the following Custom Request:
class PlanRequest extends FormRequest
{
// ...
public function rules()
{
return
[
'name' => 'required|string|min:3|max:191',
'monthly_fee' => 'required|numeric|min:0',
'transaction_fee' => 'required|numeric|min:0',
'processing_fee' => 'required|numeric|min:0|max:100',
'annual_fee' => 'required|numeric|min:0',
'setup_fee' => 'required|numeric|min:0',
'organization_id' => 'exists:organizations,id',
];
}
}
When I access it from the controller, if I do $request->all(), it gives me ALL the data, including extra garbage data that isn't meant to be passed.
public function store(PlanRequest $request)
{
dd($request->all());
// This returns
[
'name' => 'value',
'monthly_fee' => '1.23',
'transaction_fee' => '1.23',
'processing_fee' => '1.23',
'annual_fee' => '1.23',
'setup_fee' => '1.23',
'organization_id' => null,
'foo' => 'bar', // This is not supposed to show up
];
}
How do I get ONLY the validated data without manually doing $request->only('name','monthly_fee', etc...)?
$request->validated() will return only the validated data.
Example:
public function store(Request $request)
{
$request->validate([
'title' => 'required|unique:posts|max:255',
'body' => 'required',
]);
$validatedData = $request->validated();
}
Alternate Solution:
$request->validate([rules...]) returns the only validated data if the validation passes.
Example:
public function store(Request $request)
{
$validatedData = $request->validate([
'title' => 'required|unique:posts|max:255',
'body' => 'required',
]);
}
OK... After I spent the time to type this question out, I figured I'd check the laravel "API" documentation: https://laravel.com/api/5.5/Illuminate/Foundation/Http/FormRequest.html
Looks like I can use $request->validated(). Wish they would say this in the Validation documentation. It makes my controller actions look pretty slick:
public function store(PlanRequest $request)
{
return response()->json(['plan' => Plan::create($request->validated())]);
}
This may be an old thread and some people might have used the Validator class instead of using the validator() helper function for request.
To those who fell under the latter category, you can use the validated() function to retrieve the array of validated values from request.
$validator = Validator::make($req->all(), [
// VALIDATION RULES
], [
// VALIDATION MESSAGE
]);
dd($validator->validated());
This returns an array of all the values that passed the validation.
This only starts appearing in the docs since Laravel 5.6 but it might work up to Laravel 5.2

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

Laravel custom validation rule

How can i make a custom validation rule to an input which value must be an integer and starting with 120?
I already read about making custom messages but didnt understand about rules.
I want to use a regex to validate the data. ^120\d{11}$ here is my regex.
I'm new in Laravel that's why cant now imagine how to do that.
A custom validation to use it in $this->validate($request, []);
Now i'm validating data like so:
$this->validate($request, [
'user_id' => 'integer|required',
'buy_date' => 'date',
'guarantee' => 'required|unique:client_devices|number',
'sn_imei' => 'required|unique:client_devices',
'type_id' => 'integer|required',
'brand_id' => 'integer|required',
'model' => 'required'
]);
The input that i want to add custom validation is guarantee
The quickest neatest way is an inline validator in your controller action:
public function store(Request $request)
{
$validator = Validator::make($request->all(), [
'number' => [
'regex' => '/^120\d{11}$/'
],
]);
if ($validator->fails()) {
return redirect('post/create')
->withErrors($validator)
->withInput();
}
return view('welcome');
}
Where number is the name of the field being submitted in the request.
If you have a lot of validation to do, you might want to consider using a Form Request instead, as a way of consolidating a lot of validation logic.
You can create custom validations in your controller as:
$name = Input::get('field-name')
$infoValidation = Validator::make(
array( // Input array
'name' => $name,
),
array( // rules array
'name' => array("regex:/^120\d{11}$"),
),
array( // Custom messages array
'name.regex' => 'Your message here',
)
); // End of validation
$error = array();
if ($infoValidation->fails())
{
$errors = $infoValidation->errors()->toArray();
if(count($errors) > 0)
{
if(isset($errors['name'])){
$response['errCode'] = 1;
$response['errMsg'] = $errors['name'][0];
}
}
return response()->json(['errMsg'=>$response['errMsg'],'errCode'=>$response['errCode']]);
}
Hope this helps.
Since Laravel 5.5, you can make the validation directly on the request object.
public function store(Request $request)
{
$request->validate([
'guarantee' => 'regex:/^120\d{11}$/'
]);
}

How to validate laravel array with custom request?

How to validate with custom request, my request with an array key
$request = [
'link_inc_characteristic_id' => $inc_char_id[$i],
'value' => $value[$i],
'created_by' => $created_by,
'last_updated_by' => $last_updated_by,
];
$this->validate($request, [
'value['.$i.']' => 'max:30'
]);
$linkIncCharacteristicValue = LinkIncCharacteristicValue::create($request);
return Response::json($linkIncCharacteristicValue);
[EDIT] [CODE UPDATED]
display error:
Argument 1 passed to App\Http\Controllers\Controller::validate() must be an instance of Illuminate\Http\Request, array given,
The Controller::validate() is not a generic validation method, it validates requests. For this use case, simply use the validator directly:
Validator::make($data, ['value' => 'max:30']);
The error message is telling you what’s wrong:
Argument 1 passed to App\Http\Controllers\Controller::validate() must be an instance of Illuminate\Http\Request, array given
So pass the Request instance to the validate() method:
public function store(Request $request)
{
$this->validate($request, [
'value.*' => 'max:30',
]);
}
Check out the following resources:
https://laravel.com/docs/master/validation#validation-quickstart
https://laravel.com/docs/master/validation#validating-arrays
Its because I am putting the validation inside loop and not use * character to validate an array
...
for ($i=0; $i < $count ; $i++) {
...
$this->validate($request, [
'value['.$i.']' => 'max:30'
]);
...
// save etc
}
right code, put validation before loop, and use * character for array validation :
$this->validate($request, [
'value.*' => 'max:30'
]);
...
for ($i=0; $i < $count ; $i++) {
// save etc
}

Categories