Custom request validators for Multiple arrayed inputs - laravel

I have 1 form, with multiple inputs. each section can have multiple inputs, I want to create a Form Validator inside Requests for they, but don't know how to do it... This is currently how I am doing it:
public function postCreateResume(Request $request, Resume $resume, Education $education)
{
/*
* begin a transaction, because we
* are doing multiple queries
*/
DB::beginTransaction();
/*
* first we must create the resume, then we
* can use the id for the following rows
*/
$this->validate($education, [
'resume_title' => 'required',
'expected_level' => 'required',
'salary' => 'required',
'work_location' => 'required',
'year_experience' => 'required',
'about' => 'required',
]);
$resume->name = $request['resume_title'];
$resume->work_level = $request['expected_level'];
$resume->salary = $request['expected_salary'];
$resume->country = $request['work_location'];
$resume->total_experience = $request['year_experience'];
$resume->about = $request['about'];
$resume->save();
// a user can have multiple educations on their cv
foreach($request->input('education') as $education){
$this->validate($education, [
'institution' => 'required',
'degree' => 'required',
'year_begin' => 'required',
'year_finish' => 'required',
'about' => 'required',
]);
// passed our checks, insert
$education->resume_id = $resume->id;
$education->user_id = Auth::user()->id;
$education->institute = $education['institution'];
$education->degree = $education['degree'];
$education->summary = $education['about'];
$education->started = $education['year_begin'];
$education->ended = $education['year_finish'];
if(!$education->save()){
DB::rollback();
return redirect()->back()->withErrors("There was an error creating this resume")->withInput();
}
}
// a user can have multiple employment on their cv
foreach($request->input('experience') as $employment){
$this->validate($employment, [
'company' => 'required',
'title' => 'required',
'country' => 'required',
'year_begin' => 'required',
'year_finish' => 'required',
'notes' => 'required',
]);
// passed our checks, insert
$employment->resume_id = $resume->id;
$employment->user_id = Auth::user()->id;
$employment->name = $employment['title'];
$employment->company = $employment['company'];
$employment->country = $employment['country'];
$employment->started = $employment['year_begin'];
$employment->ended = $employment['year_finish'];
$employment->summary = $employment['notes'];
if(!$employment->save()){
DB::rollback();
return redirect()->back()->withErrors("There was an error creating this resume")->withInput();
}
}
return redirect()->back()->withSuccess("You have created a resume")->withInput();
}
Notice I have the validate inside each of the foreach in case the user has chosen more than 1 (in this example) work experience, or education, what I am trying to do is move the $this->validate inside the Requests folder, how can I achieve this?
I am using a foreach because I can have unlimited sections, see the image as to why;

Since laravel 5.4 you can pass arrays to the validator itself, for exaple
<input name="myarray[0]['test'] type="text">
Can now be validated like so
$this->validate($request, [
'myarray.*.test' => 'required'
]);
https://laravel.com/docs/5.4/validation#validating-arrays
Validating array based form input fields doesn't have to be a pain. 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',
]);
Likewise, you may use the * character when specifying your validation messages in your language files, making it a breeze to use a single validation message for array based fields:
'custom' => [
'person.*.email' => [
'unique' => 'Each person must have a unique e-mail address',
]
],

Related

how to add laravel conditional validation

I want to add conditional validation to my request. I have different user roles and different fields for some users.
I want to check if the user role is business then some fields are required and if the user is a worker then business user fields are not required.
$this->validate($this->_request, [
'name' => 'required',
'email' => ['required', 'string', 'email', 'max:255', 'unique:users'],
'phone' => ['required', 'max:22'],
'municipality_of_origin' => 'required',
]);
These are required for all users. Now I want to check if a user is business
if($role == 'business'){
'company_name' => 'required',
'company_title' => 'required',
}
if($role == 'worker'){
'designation' => 'required',
'salary' => 'required',
}
$data = $request->safe()->only('name', 'email', 'phone', 'municipality_of_origin');
$user = User::create($data);
if($role == 'business){
$business_user = $request->safe()->only('company_name', 'company_title');
$business_user['user_id'] = $user->id;
// business is hasOne relationship with User model.
$user->business->create($business_user);
}
Is there any best way to handle this type of conditional validation in laravel? I'm using Laravel 9.
I try Form validation but don't understand how to use FormRequest for this type of validation.
$rules = [];
$rules['name'] = 'required';
$rules['email'] = ['required', 'string', 'email', 'max:255', 'unique:users'];
$rules['phone'] = ['required', 'max:22'];
$rules['municipality_of_origin'] = 'required';
if ($this->attributes->has('some-key')) {
$rules['other-key'] = 'required|unique|etc';
}
and problem is $this->attributes->has() method return null all the time.

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;
}

How to make validation rules for storing and update users if there are unique attributes

I use username as an id to login and made username and email as unique.
Whenever I made username and email, validation rules check coming data and there is no problem with it because username and email would be new and unique.
The problem occurs when I update. when I update the attributes, I don't need to change the username mostly but the rules are expecting unique, username.
what is the best practice for updating unique attributes with validation rules?.
Update user method
public function updateUser($req, $id)
{
$user = User::where('user_id', $id)->firstOrFail();
$user->username = $req->input('username');
$user->password = Hash::make($req->input('password'));
$user->email = $req->input('email');
$user->first_name = $req->input('first_name');
$user->last_name = $req->input('last_name');
$user->phone = $req->input('phone');
$user->emergency_phone = $req->input('emergency_phone');
$user->profile_photo = $req->input('profile_photo');
$user->role = $req->input('role');
$user->status = $req->input('status');
$user->save();
return $this->filterUsers([$user]);
}
Rules
protected $rules = [
'username' => 'required|max:20|unique:users',
'email' => 'required|string|email|max:255|unique:users',
'password' => 'required',
// **in Production **
// 'password' => [
// 'required',
// 'min:6',
// 'regex:/^.*(?=.{3,})(?=.*[a-zA-Z])(?=.*[0-9])(?=.*[\d\X])(?=.*[!$#%]).*$/',
// 'confirmed'
// ],
/**
* Three of the five rules.
* English uppercase characters (A – Z)
* English lowercase characters (a – z)
* Base 10 digits (0 – 9)
* Non-alphanumeric (For example: !, $, #, or %)
* Unicode characters
*/
'first_name' => 'required|string|max:255',
'last_name' => 'required|string|max:255',
'phone' => 'required|regex:/^([0-9\s\-\+\(\)]*)$/|min:5',
'role' => 'required'
];
You can use
'username' => 'required|max:20|unique:users,username,' . $id',
if your users table primary key is id, if it is something else like user_id, then it will become
'username' => 'required|email|unique:user,username,' . $request->input('user_id') . ',userid',
so syntax is
'input_field' => 'unique:<table name>,<column name for this input field>, <unique id>, <unique id column in table>';
At edit time it will check for a unique username so we avoid unique for a current edit id
In the update method your validation rules as per below:
protected $rules = [
'username' => 'required|max:20|unique:users,username,' . $id',
'email' => 'required|string|email|max:255|unique:users,email,' . $id',
'password' => 'required',
'first_name' => 'required|string|max:255',
'last_name' => 'required|string|max:255',
'phone' => 'required|regex:/^([0-9\s\-\+\(\)]*)$/|min:5',
'role' => 'required'
];
You need to use laravel validator class in controller Use Validator;
And use something like this:
$error = Validator::make($req->all(), $rules);
More examples here in docs of Validation.

Validation : Laravel

In ContactsRequest.php
public function rules()
{
return [
'org_id' => 'required',
'name' => 'required',
'office' => 'required',
'mobile' => 'required_without:home',
'home' => 'required_without:mobile'
];
}
So basically what i want is , i have a form which will be taking the attributes specified in the code. But i want to modify code so that entering either one of 'home' or 'mobile' will allow me to create the new user.
What should be done.Any help would be appreciated

Validate whether multiple fields are unique simultaneously in laravel 5

This my request class rules.
return [
'title' => 'required|unique:event_cals,title',
'eventDate' => 'required|date|after:yesterday',
'venue' => 'required',
'time' => 'required',
'type' => 'required',
'unique:event_cals,eventDate,NULL,id,venue,$request->venue,time,$request->time'
];
I want to validate a rule like below.
'eventDate' && 'venue' && 'time' => 'unique'
There I need to check if there any row without same eventDate, venue and time altogether. Anyone knows how to declare such a rule?
This is the snapshot of db table.
Here is the possible solution:
<?php
return [
'title' => 'required|unique:event_cals,title',
'eventDate' => 'required|date|after:yesterday',
'venue' => 'required',
'time' => 'required',
'type' => 'required',
'event_date' => "unique:event_cals,event_date,NULL,id,venue,{$request->venue},time,{$request->time}",
];
I again want to highlight that; if you want that validator to work, you should make sure that the event_date and time should be correctly formatted.
An example unique check with additional wheres from our running project's update requests:
/**
* Get the validation rules that apply to the request.
*
* #return array
*/
public function rules()
{
$id = $this->route('money');
return $rules = [
'name' => "required|string|min:3|max:255|unique:moneys,name,{$id},id,deleted_at,NULL,access,public",
];
}

Resources