I am building a Book Portal with Laravel. I have a unique validation rule on name to books.
$request->validate([
'name' => 'required|unique:books',
'about' => 'required',
'dsecription' => 'required',
'image' => 'required|mimes:jpeg,bmp,jpg,png|between:1, 6000',
'author_id' => 'required',
'publisher' => 'required',
'recommended' => 'required',
'epub_url' => 'required',
'year'=> 'required',
'pages' => 'required',
]);
I found out that an Author can have the same book name. Using unique on the name, will not allow me to upload.
I am thinking, if there is a way, I can check the author and the name of the book i.e
Check if the author has the same name, then apply the unique rule on name else upload.
I didn't find any solution for this. That's why I made my own custom validation like this :
$request->validate([
'name' => 'required|unique:books',
'author_id' => 'required',
// ...
]);
$data = Book::where('author_id', $request->author_id)->where('name', $request->name)->first();
if(!empty($data)) {
return redirect()->back()->withErrors('This name already taken'); // error message
}
You can try using the extra where conditions that can be passed to the unique rule to apply the unique constraint under certain conditions:
// we will make sure 'author_id' is an existing value
'author_id' => 'bail|required|integer|exists:authors,id',
'name' => [
'bail',
'required',
Rule::unique('books')
->where('author_id', (int) $request->input('author_id')),
],
Assuming author_id is on the books table.
Laravel 7.x Docs - Validation - Rules - unique
Related
I have 2 different tables based on their types: User & Buyer.
I am validating "buyers" data but it checks in the "users" table rather than in the "buyers" table, Is there any way to ask Validator Facade to check in the "buyers" table.
$validator = Validator::make($request->all(), [
'name' => 'required',
'user_type' => 'required',
'phone' => 'required|unique:users|max:11|min:11',
'email' => 'required|email|unique:users',
'password' => 'required|min:8',
'passowrd_confirmation' => 'required|same:password',
]);
https://laravel.com/docs/8.x/validation#specifying-a-custom-column-name
According to the documentation, you can indicate a specific field of any of your tables for validation. In this way you can do:
'name' => 'required:buyers, name'
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;
}
I want to do "unique" validation on multiple fields. I have written below validation rule but not sure how to include brand_id and company_id in it
$request->validate([
'name' => 'required|string|unique:products',
'company_id' => 'required',
'brand_id' => 'required',
]);
So what I am trying to do is, ADD PRODUCT but check if the name is unique for the given company_id and brand_id. How can I do that?
We can use Rule::unique() function to add custom conditions to unique validation.
$request->validate([
'company_id' => 'required',
'brand_id' => 'required',
'name' => [
'required',
'string',
Rule::unique('products')->where(function($query) {
$query->where('company_id', request('company_id'));
$query->where('brand_id', request('brand_id'));
}),
],
]);
Sometimes you may wish to stop running validation rules on an attribute after the first validation failure. To do so, assign the bail rule to the attribute:
$request->validate([
'name' => 'bail|required|string|unique:products',
'company_id' => 'bail|required',
'brand_id' => 'required',
]);
You can add additional wheres after the ignore options (the NULL,id below), e.g.:
$request->validate([
'company_id' => 'required',
'brand_id' => 'required',
'name' => 'required|string|unique:products,name,NULL,id,company_id,'.request('company_id').',brand_id,'.request('brand_id'), '
]);
laravel 5
In laravel 5 form validation I need email to be only unique for a certain field's id in the db table.
$this->validate($request,[
'name'=>'required',
'email' => 'unique:users,email,',
'password'=>'required',
]);
You can try this way:
$companyId = $request->get('company_id'); // selected company
$this->validate($request,[
'name' => 'required',
'email' => [
'required',
"unique:users,email,NULL,id,company_id,$companyId"
],
'password'=>'required',
]);
If you want to ignore a specific id in the database, you can use ignore. For example, when a user is updating his profile, we want to allow him to send his email address, it should not be considered a not unique.
Here is the docs details. And here is your code updated to match that:
$this->validate($request,[
'name'=>'required',
'email' => [
\Illuminate\Validation\Rule::unique('users', 'email')->ignore($user->id),
],
'password'=>'required',
]);
However, if want to ignore more than one id or want to customize the query, you need to add a where clause:
$this->validate($request,[
'name' => 'required',
'email' => [
'required',
\Illuminate\Validation\Rule::unique('users')->where(function ($query) {
// Add any constraints you want for the query here.
return $query->whereNotIn('id', [1, 2, 3, 4]);
}),
],
'password'=>'required',
]);
Use Third and Fourth param to ignore for company_id
$company_id = 1;// Company will be here
And in validation
'email' => 'unique:users,email,'.$company_id.',company_id',
I use soft deletes which I then ignore/exlude in the validation rules in Laravel 5.3.
How do I enforce two ignores in a validation array for updates?
'number' => "required|unique:customers,number,NULL,id,company_id,
$company_id},deleted_at,NULL",
I need to add the exclusion of the current record as well.
I found the answer myself. For your information(field = number) :
$validator = Validator::make($request->all(),
[
'number' => "required|unique:customers,number,{$id},id,company_id,{$company_id},deleted_at,NULL",
'name' => 'required',
'street' => 'required',
'streetnumber' => 'required',
'zipcode' => 'required',
'city' => 'required',
]);