I am validating an array in Laravel 5.7 but the validator passes when I expect it to fail.
$validator = Validator::make($request->all(), [
'user_reg_email' => 'required|max:255|email|exists:users,email',
'service_start_date' => 'required|before_or_equal:today',
'service_end_date' => 'nullable|after:service_start_date',
'role' => 'array|min:1|unique:provider_user,role,NULL,id,user_email,' . $request->user_reg_email . ',provider_domain,' . $request->prov,
]);
The payload is as below:
{
_token: "d5VYhirRAn3Zb9bCKHKQiuLNXkHfEP4hEs0bAZvj",
prov: "email.com",
user_reg_email: "john#email.com",
service_start_date: "2019-03-03",
service_end_date: null,
role: [
null
],
}
The role validation passes but I expect it to fail. How do I get the expected results?
'role' => 'array,...' will validate that the role field is an array, which it is.
To validate the items within the array, you also need to include this rule:
'role.*' => unique:provider_user,...
Related
I have a trouble validating an array members in validation for Laravel. For array itself it passes, but for elements themselves, it fails.
Open json in console, shows structure of data being sent. It's clearly a integer. Since it's associative array, not sure how it even finds it's value as show in error handling red rectangle on the bottom of the page.
Here is my validation logic:
$validation = Validator::make(
$request->all(),
[
'load_place' => 'required|max:255',
"unload_place" => 'required|max:255',
"comment" => 'required|max:255',
'time_in' => 'required',
'time_out' => 'required',
"vehicles" => 'required|array',
"vehicles.*" => "required|integer",
'operator_id' => 'required|integer',
'sec_id' => 'required|integer'
]
);
And here is how it's returned:
if($validation->fails()){
$response = array(
"message" => "Failed",
"errors" => $errors,
"test" => $request->vehicles[0]
);
return response()->json($response);
}
That request[0], is that number at the bottom.
Edit1:
Keys in that marked array, are set on frontend, they are not not predefined. They can be whatever.
Change "vehicles.*" => "required|integer", to "vehicles.*.vehicle_id" => "required|integer", and it should work.
Keys is set on frontend, they are not not predefined. That what i am trying to say.
Try to replace "vehicles.*" => "required|integer", with new Rule::forEach rule for nested array data - guess it should work.
"vehicles.*" => Rule::forEach(function($value, $attribute) {
return [
Rule::integer()->min(1) //min(1) as eg if it's for an id field which cannot be 0
];
}),
so I am trying to loop through an array of objects to update certain values in my database with the values from the object
When I run this loop in my controller
foreach($statuses as $status){
$workflow->statuses()->where('id', $status->id)->update([
'status' => $status->status
]);
};
It gives me error trying to get property of non-object
When I do a `return response($request->statuses) this is the data structure I see in the console
here is the complete controller
public function workflowStatuses(Request $request, Workflow $workflow)
{
// validate form data
$data = $request->validate([
'workflow' => 'required|string',
]);
// validate form data
$oldStatuses = $request->validate([
'statuses' => 'required|array'
]);
// validate form data
$newStatuses = $request->validate([
'newStatuses' => 'required|array',
]);
$workflow->update($data);
$statuses = $oldStatuses;
foreach($statuses as $status){
$workflow->statuses()->where('id', $status['id'])->update([
'status' => $status->status
]);
};
$workflow->statuses()->saveMany($newStatuses);
return response($workflow, 200);
}
You can think of the return value of $request->validate() as the array of all request input filtered to only include the data that's being validated. If that validated data contains arrays, you'll have a multi-dimensional array.
Here, $oldStatuses is going to be an array that contains a key named statuses that contains the actual array you're looking for.
$oldStatuses = $request->validate([
'statuses' => 'required|array'
]);
// $statuses should get 'statuses' out of this validated array
$statuses = $oldStatuses['statuses'];
Instead, you may want to clean this up and not call validate three times. It's usually better to run all the validation rules in one validate() call, unless you have good reason to logically separate them.
$validated = $request->validate([
'workflow' => 'required|string',
'statuses' => 'required|array',
'newStatuses' => 'required|array',
]);
$statuses = $validated['statuses'];
Try:
foreach($statuses as $status){
$workflow->statuses()->where('id', $status['id'])->update([
'status' => $status['status'] //$status['status'] should also be accessed by key
]);
};
I have this request:
GET http://example.com/test?q[]=1&q[]=2&q[]=3
And I have this route:
Route::get('test', function(Request $req) {
$req->validate(['q' => 'array']);
});
How should I do to add other validation rules to each element of this array using Laravel validator? For example, I want to check that each q value has a minimum of 2.
Thank you for your help.
Take a look at the documentation about validating arrays.
$validator = Validator::make($request->all(), [
'person.*.email' => 'email|unique:users',
'person.*.first_name' => 'required_with:person.*.last_name',
]);
You can also do this in your controller using the Request object, documentation about validation logic.
public function store(Request $request)
{
$validatedData = $request->validate([
'title' => 'required|unique:posts|max:255',
'body' => 'required',
]);
// The blog post is valid...
}
There is a third option for when you have a lot of validation rules and want to separate the logic in your application. Take a look at Form Requests
1) Create a Form Request Class
php artisan make:request StoreBlogPost
2) Add Rules to the Class, created at the app/Http/Requestsdirectory.
public function rules()
{
return [
'title' => 'required|unique:posts|max:255',
'body' => 'required',
];
}
3) Retrieve the request in your controller, it's already validated.
public function store(StoreBlogPost $request)
{
// The incoming request is valid...
// Retrieve the validated input data...
$validated = $request->validated();
}
You can do:
Route::get('test', function(Request $req) {
$req->validate([
'q' => 'array',
'q.*' => 'min:2'
]);
});
For more information on validation of arrays, see => laravel.com/docs/5.6/validation#validating-arrays
Suppose I got an array of users
users: [
{
"id": 1,
"name": "Jack",
},
{
"id": 2,
"name": "Jon"
}
]
I would validate it like below :
$request->validate([
'users[*]'=> [
"id" => ["integer", "required"],
"name" => ["string", "required"]
]
]);
Here * acts as a placeholder
This question somewhat follows on from a previous question I asked about implementing validation when performing a search in a Cake 3.x application: CakePHP 3.x search form with 11 different models
I've been reading the documentation on Using Custom Validation Rules.
I have added the following to my Model/Table/EcsTable.php:
public function validationSearch($validator)
{
$extra = 'Some additional value needed inside the closure';
$validator->add('value', 'custom', [
'rule' => function ($value, $context) use ($extra) {
return false;
},
'message' => 'The title is not valid'
]);
return $validator;
}
This is a copy of what is given in the docs except I have added return false because I'm trying to test the validation method producing an error.
In my Controller I have the following:
$ecs_entity = TableRegistry::get('Ecs')->newEntity(
$this->request->getData(),
[
'validate' => 'search', // tells cake to use validateSearch
]
);
I cannot get this to generate a validation error. If I submit my form (so that the request data is submitted) and then do debug($ecs_entity); the errors property is an empty array:
object(Cake\ORM\Entity) {
'ecs' => [
'value' => '124'
],
// ...
'[original]' => [],
'[virtual]' => [],
'[errors]' => [],
'[invalid]' => [],
'[repository]' => 'Ecs'
}
Why is this? I am planning on writing logic inside my closure inside validationSearch which validates the data passed. However, I can't even get it to produce an error so haven't gone this far with it. Am I implementing this in the wrong way?
As per the original question I'm trying to do things in the proper "Cake way" of writing validation. I'm getting to the point where I'm seriously considering abandoning it and just sticking everything in the Controller, because it's so tedious to pass the data around - and involves more lines of code when I could just validate it right there in the controller.
The data you are passing to the newEntity call is not in valid format.
It looks like you are passing something like
[
'ecs' => [
'value' => 123
]
]
When it should be:
[ 'value' => 123 ]
The debug output for a valid Ecs entity should look like this:
object(Cake\ORM\Entity) {
'value' => '123',
'[new]' => true,
'[accessible]' => [
'*' => true
],
'[dirty]' => [
'value' => true
],
'[original]' => [],
'[virtual]' => [],
'[errors]' => [],
'[invalid]' => [],
'[repository]' => 'Esc'
}
As you can see value is a direct property of the object.
Without seeing your Form I can guess you have created it like:
$this->Form->control( 'ecs.value')
instead of
$this->Form->control( 'value' );
There something I don't understand.
When passing input to the controller I have it validate with laravel, example:
$this->validate($request, [
'user_id' => 'required',
'post_id' => 'required',
'body' => 'required'
]);
now the point is, do I have to make a condition before inserting in the DB? and if so how? I mean (pseudo code)
if data is validated { store in DB }
or will validate get ahold of everything and simply stop if erros are found?
Try this :
// define rules
$rules = array(
'user_id' => 'required',
'post_id' => 'required',
'body' => 'required'
);
$validator = Validator::make(Input::all(), $rules);
if ($validator->fails())
{
// something
// return Redirect::back()
// ->withErrors($validator) // send back all errors to the login form
// ->withInput();
}
else
{
// something
$data->save(); // save your data
}
If validation fails the errors are pushed into session and the user will be redirected to the previus location.
If the validation goes well, the code after $this->validate(...) will be executed.