Array Validation: unique validation on multiple columns - laravel

I am trying to check unique validation on three columns employee_id,designation_id,station_id but the data are coming as an array which is making my situation unique and different from other SO questions/answers. I already checked few question like below: checks unique validation on multiple columns
But in my case, I can't get the value as they are inside an array. I also tried to implement Custom Rule or Request but in vain. For all the attempts, I am failing to get the field value such as $request->employee_id as they are inside an array for my case. May be I'm not trying it right.
Controller Code:
$this->validate($request, [
'posting.*.employee_id' => 'required,unique: // what to do here ??',
'posting.*.designation_id' => 'required',
'posting.*.station_id' => 'required',
'posting.*.from_date' => 'required|date',
]);
I am trying to validate uniqueness for both create and update (along with ignore $this->id facility) but don't know how to implement it here for array. It would be no problem if there was no array. Any help/suggestion/guide is much appreciated. Thanks in advance.

You can do this by creating a rule i.e UniquePosting so your controller code would look like
$this->validate($request, [
'posting' => ['required'],
'posting.*' => ['required', new UniquePosting()],
'posting.*.employee_id' => 'required',
'posting.*.designation_id' => 'required',
'posting.*.station_id' => 'required',
'posting.*.from_date' => 'required|date',
]);
Now inside your UniquePosting rule passes function will look like
public function passes($attribute, $value) {
$exists = Posting::where(['employee_id' => $value['employee_id'], 'designation_id' => $value['designation_id'],'station_id' => $value['station_id')->exists();
return !$exists;
}
Add any change if needed, overall that's the concept for testing uniqueness of the whole array.

Related

Custom errorBag for different cards in one livewire form

My livewire form has four cards in it, and users can choose which cards they would like to answer, and it can be more than one card. So I did a condition that checks which cards are selected and only validates data and creates database entry based on the cards selected.
CardFormComponent.php:
public function submit()
{
$user = auth()->user();
if($this->showDiv1){
$salary_data = $this->validate([
'emp_name' => 'required',
'emp_length' => 'required',
'emp_monthly_gross_salary' => 'required',
'monthly_allowance' => 'required',
])->validateWithBag('salary_error');
}
if($this->showDiv2){
$gig_data = $this->validate([
'role' => 'required',
'est_earnings' => 'required',
])->validateWithBag('gig_error');
}
if($this->showDiv3){
$self_data = $this->validate([
'business_type' => 'required',
'other_type' => 'required',
'date_com_trade' => 'required',
'no_of_emp' => 'required',
'business_registration_number' => 'required',
'office_ph_no' => 'required',
'share_of_bus' => 'required',
'last_2_year_profit' => 'required'
])->validateWithBag('self_error');
}
if($this->showDiv4){
$investment_data = $this->validate([
'inv_name' => 'required',
'yearly_earning' => 'required',
])->validateWithBag('invest_error');
}
$user->user_current_step = Constant::CURR_STEP_COMMITMENT;
$user->save();
alert('success','Your income are saved.');
return redirect()->route('borrower.landing');
}
So this code works for saving the user input from all the cards, however, for example when I chose two cards, and submit an empty form, error messages only appear in the first card. When tested individually, error messages appear for all the cards, so I am sure that its not the problem with the display of the messages. My assumption is that once the validation fails in the first card, it straight away return to the view before going through the other loops. Is there any way to prevent the controller returning to the view before it goes through all the validation?
Additional note, a senior suggested me to use error bags for each cards, thus explaining the validateWithBag('name) in the code, but from my research it seems like I can only pass one error bags to the view? And it also seems like validateWithBag() does automatic redirection.
Is there any way from my code or any alternative for me to get all the error messages displayed according to the cards selected?
I got this answer from my facebook posting for this question and I thought I should share it here.
Answer:
Yes, the Laravel validate() method will stop execution of the code and return the errors.
You could try running a validate() only once at the end of the if statements, inside each if statement, you should add the rules that represent your Livewire models.
Hope this answers your question and helps you out.
The screencap on how to write the code

Conditional Validation with dependency to other fields in import

I am trying to validate import data using Laravel Excel. I got through to using required_if when a field is required when another field has a certain value. But what if validation rule I want to implement in this scenario is regex instead of required.
public function collection(Collection $rows){
$validator = Validator::make($rows->toArray(), [
'*.question_categories' => 'required',
'*.question' => 'required',
'*.question_type' => 'required',
'*.mark' => 'required',
'*.correct_answer' => ['required_if:*.question_type,Single Answer',
]
])->validate();
// Code below
}
Here I want to check value of "question_type" to determine the regular expression for "correct_answer".
I am using Laravel 6x.

Laravel, use only custom rule class for validation?

I have some dynamic fields and can't use usual field validation. My question is, how can I use only my custom rule class without defining if it's required or not?
This doesn't work:
$this->validate($request, [
'social_links.fb' => new SocialFieldValidation($fieldDataFb),
'social_links.linkedin' => new SocialFieldValidation($fieldDataLinkedIn),
'social_links.twitter' => new SocialFieldValidation($fieldDataTwitter)
]);
To get this work I need to add something like:
$this->validate($request, [
'social_links.fb' => ['sometimes', new SocialFieldValidation($fieldDataFb)],
'social_links.linkedin' => ['sometimes', new SocialFieldValidation($fieldDataLinkedIn)],
'social_links.twitter' => ['sometimes', new SocialFieldValidation($fieldDataTwitter)]
]);
To use always validation class I need to set required or sometimes but I would need only to use validation class without other definitions, is that possible?
As mentionned in your comment, if putting your custom rule validation in array works but you want this working in case of null value, then you need to do use the nullable validation:
$this->validate($request, [
'social_links.fb' => ['nullable', new SocialFieldValidation($fieldDataFb)],
'social_links.linkedin' => ['nullable', new SocialFieldValidation($fieldDataLinkedIn)],
'social_links.twitter' => ['nullable', new SocialFieldValidation($fieldDataTwitter)]
]);
If you need the documentation:
https://laravel.com/docs/8.x/validation#rule-nullable
https://laravel.com/docs/8.x/validation#a-note-on-optional-fields

Laravel 5.2 Validate File Array

I have a form with three fields: title, body and photo[]. I'm trying to validate it so that at least one item is filled in, but I can't seem to get it to work. If I upload a file I still receive an error for title and body.
public function rules()
{
return [
'title' => 'required_without_all:body,photo.*',
'body' => 'required_without_all:title,photo.*',
'photo.*' => 'required_without_all:title,body',
'photo.*' => 'mimes:jpeg,gif,png',
];
}
Update: Jonathan pointed out that I had my rules wrong. I've fixed them and am now using this. It's still not working; when I try to upload a photo I get the error message that the other fields are required.
public function rules()
{
return [
'title' => 'required_without:body,photo.*',
'body' => 'required_without:title,photo.*',
'photo.*' => 'required_without:title,body|mimes:jpeg,gif,png',
];
}
If you're looking to ensure the photo field is an array then you need 'photo' => 'array' and then you can use 'photo.*' => '' for the other validations of the array's children.
The rules are separated by a pipe character | so if you were going to combine the two in your example it would be 'photo.*' => 'required_without_all:title,body|mimes:jpeg,gif,png',. I don't see you using the pipe to separate rules so I can't be sure you are aware of it.
This may have been where you were going wrong in the first place (two keys in the associative array that are identical) and some kind of precedence taking affect negating one of the rules.
You could try something like this (for the record I think you were on the right track to begin with using required_without_all as this stipulates the need to be required if all of the given fields are missing):
public function rules()
{
return [
'title' => 'required_without_all:body,photo',
'body' => 'required_without_all:title,photo',
'photo' => 'array',
'photo.*' => 'required_without_all:title,body|mimes:jpeg,gif,png',
];
}
Reference

Laravel 5 validation rules

previously I have used validation within a Request class e.g.
public function rules()
{
return [
'userName' => 'required', 'min:3',
'userEmail' => 'required|email',
'departmentId' => 'required',
'slug' => 'required',
];
}
But I now have another form but I can't see any options within the documentation that might help me.
Basically, lets say I have a form with the same fields as the validation above. The only time validation should fail is if ALL fields contain absolutely no data. So if I put something like "hi" within the slug input and submit, it should pass the validation.
Would something like this be possible?
Thanks
You can probably use the required_without_all validation rule.
http://laravel.com/docs/5.1/validation#rule-required-without-all
The field under validation must be present only when all of the other
specified fields are not present.
It would give you something like
public function rules()
{
return [
'userName' => 'required_without_all:userEmal,departmentId,slug','min:3',
'userEmail' => 'required_without_all:userName,departmentId,slug|email'
...
];
}
But it's not very handy if you have a lot of fields.
If you have to deal with many fields, creating a custom validator might be a better solution.
http://laravel.com/docs/5.1/validation#custom-validation-rules

Resources