63

I am having my validation rules for unique in the update section.

In inserting or adding the unique rule is 'Email' => array('unique:driver_details'), and it will check for the unique coloumn.

But this fails for the update section. While updating it satisfies the other rules and in the unique of email it is checking itself for the unique coloumn and it fails but seeing its own field.

So, how can i check for the unique except its own value in the database ?

  • possible duplicate of [Laravel 4 validation email unique constraint](http://stackoverflow.com/questions/28144724/laravel-4-validation-email-unique-constraint) – patricus Jan 28 '15 at 18:42
  • @patricus: I got your question, but in your answer you didn't say about how to get the $id, it will be ok if they do validate for their own profile they can get their id by `Auth::user()->id` and in case of admin doing those part to others parts, should i set session and get inside model ,,, ??? –  Jan 29 '15 at 01:38
  • How are you currently getting the id of the record you are trying to update? – patricus Jan 29 '15 at 01:45
  • i am sending all the values to the model, `$validation = Validator::make($DriverData, DriverModel::$updaterules);` –  Jan 29 '15 at 01:55
  • I have posted a new question here, which would be clear, can you have a look at here ,, http://stackoverflow.com/questions/28205762/how-to-pass-the-value-inside-the-model-for-checking-in-the-rules –  Jan 29 '15 at 01:55

23 Answers23

88

This forces to ignore specific id:

'email' => 'unique:table,email_column_to_check,id_to_ignore'

replace segments table, email_column_to_check, id_to_ignore in above example

You could check it here http://laravel.com/docs/4.2/validation#rule-unique

cespon
  • 5,630
  • 7
  • 33
  • 47
user3714582
  • 1,830
  • 13
  • 22
  • 4
    But How can i get the `id_to_ignore` inside the model, I can't get the `Auth::user()->id` because this is admin part and doing validation for other users.. –  Jan 29 '15 at 01:35
  • 1
    you can get it from the request like this : `request()->route('route wildcard')->id` – Jelly Bean Aug 01 '19 at 12:07
  • If you defined your route like this: `Route::apiresource('car', 'Api\CarController')` then you can retrieve the resource's id like this: `request()->route('car')` or `request()->route()->parameters['car]`. If you are inside a request object you can use `$this` instead of `request()` as well. – totymedli Nov 16 '21 at 15:52
35

For those using Laravel 5 and Form Requests, you may get the id of the model of the Route-Model Binding directly as a property of the Form Request as $this->name_of_the_model->id and then use it to ignore it from the unique rule.

For instance, if you wanted to have unique emails, but also allow an administrator to edit users, you could do:

Route:

Route::patch('users/{user}', 'UserController@update');

Controller:

public function update(UserRequest $request, User $user) 
{
    // ...
}

Form Request:

class UserRequest extends FormRequest
{
    // ...
    public function rules()
    {
        return [
            'name' => 'required|string',
            'email' => [
                'required',
                'email',
                Rule::unique('users')->ignore($this->user()->id, 'id')
            ],
            //...
        ];
    }
    //...
}

Please note that we are ignoring the user that is being edited, which in this case could be different than the authenticated user.

senty
  • 12,385
  • 28
  • 130
  • 260
Arian Acosta
  • 6,491
  • 1
  • 35
  • 32
  • `Rule::unique('users')->ignoreModel($this->user)` may also be used. – Daniel Cheung Nov 13 '19 at 15:40
  • 1
    `Rule::unique('users')->ignoreModel($this->user())` is the correct syntax as of Laravel 9 – senty Mar 22 '22 at 11:36
  • 1
    I just tested and these aren't the same: `$this->user` gives the user as resolved by Route-Model Binding, whereas `$this->user()` gives the current user (i.e. the same as calling `auth()->user()`) – PlumsAhoy Jun 13 '22 at 16:55
16
$request->validate([
    'email' => 'unique:table_name,email,' . $user->id
]);
Ronish
  • 181
  • 1
  • 3
  • 4
    Welcome to StackOverflow! Kindly consider adding some explanation with your code as well, so that OP and other users may gain insight as to how and why your answer is applicable. :) – Uzair A. Nov 23 '18 at 06:02
15

I am using Laravel 5.2

if your primary key is named 'id' table name is users_table and You want to update user_name so do it this way

'user_name'  =>  'required|unique:users_table,user_name,'.$id

if your primary key is not named 'id' In my case my primary key is user_id and table name is users_table and You want to update user_name

so do it this way

'user_name' => 'required|unique:users_table,user_name,'.$id.',user_id'
Nirav Bhoi
  • 559
  • 9
  • 17
10

Try this

'email' => 'unique:table_name,column_name,'.$this->id.',id'

$this->id will be the value from your request

mwafi
  • 3,946
  • 8
  • 56
  • 83
  • My Question is $this->id will be validated value?? I meant to say what will happen if I pass any string value in id where it is integer field or something like ' or 1=1 ' value. I want to know is it safe from SQL Injection? – Er Jagdish Patel Jun 06 '22 at 12:55
7

Include Rule by writing

use Illuminate\Validation\Rule;

and write your validation code as follows:

 'Email' => [required,
            Rule::unique('driver_details')->ignore($id),
            ]

Here $id is the id of the email that you want to ignore during validation which is obtained from the controller.

7

Check This,

'email' => [
        'required',
        Rule::unique('users')->ignore($user->id),
    ],

Check here https://laravel.com/docs/7.x/validation#rule-unique.

tarek suvo
  • 81
  • 1
  • 2
6

This took me a while to figure out but when you are dealing with update/create requests you also have access to the request object. Here I am enforcing that client names are unique but allowing currently edited client.

class CreateUpdateClientRequest extends FormRequest
{
    /**
     * Get the validation rules that apply to the request.
     *
     * @return array
     */
    public function rules()
    {
        return [
            'name' => [
                'required',
                'string',
                'min:3',
                'max:50',
                Rule::unique('clients')->ignore($this->request->get('id'))
            ],
            'primary_contact_name' => 'required|string|min:3|max:50',
            'primary_contact_email' => 'required|string|email|min:5|max:50',
            'primary_contact_phone' => 'nullable|string|min:5|max:50',
            'secondary_contact_name' => 'nullable|string|min:3|max:50',
            'secondary_contact_email' => 'nullable|string|email|min:5|max:50',
            'secondary_contact_phone' => 'nullable|string|min:5|max:50',
            'notes' => 'nullable'
        ];
    }
}
Juha Vehnia
  • 1,255
  • 12
  • 15
6

In Laravel 6 app it helped me to exclude current user's email from validation:

use Illuminate\Validation\Rule;

public function update(Request $request, $id)
{
    $request->validate([
        'email' => [
            'email',
            'required',
             Rule::unique('claims')->ignore($id),
        ],
    ]);

    // ...
}
yesnik
  • 4,085
  • 2
  • 30
  • 25
2
<?php

namespace App\Http\Requests\Admin\User;

use App\Model\User;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Http\Request;


class UpdateRequest extends FormRequest
{
    protected $id;

    public function __construct(Request $request)
    {
        $this->id = (integer) $request->route()->user;
    }

    /**
     * Determine if the user is authorized to make this request.
     *
     * @return bool
     */
    public function authorize()
    {
        return true;
    }

    /**
     * Get the validation rules that apply to the request.
     *
     * @return array
     */
    public function rules()
    {
        return [
            'first_name' => 'required|max:20',
            'last_name' => 'nullable|max:20',
            'mobile' => 'required|size:10|unique:users,mobile,'.$this->id,
           
        ];
    }
}
Arun
  • 21
  • 1
2

there is a shorter way, in my case I'm using route model binding, the URL format is

/something/{user}/something

return [
        'level' => 'required|max:5|unique:users,level,'. optional($this->user)->id,
    ];
sh6210
  • 4,190
  • 1
  • 37
  • 27
2

Laravel 8:

    $request->validate([
        'email' => 'required|unique:users,email,'. $user->id,
    ]);
lky
  • 1,081
  • 3
  • 15
  • 31
1

Been facing this issue for a while also. Try this:

$v = Validator::make($request->all(), [
    'email' => ['required',
    Rule::unique('<table_name>')->ignore(<your_table_id_to_ignore>),
    ]
]);

Works on Laravel 5.8. I don't know if it does work on lower versions of Laravel.

fabian
  • 21
  • 3
1

Try to use the Rule::unique('users')->ignore(Auth::id())

    //Validation
    $data = $request->validate([
        'username' => ['required', Rule::unique('users')->ignore(Auth::id()), 'min:4'],               //Verificar que este seleccionado sea único {Exceptuando mi mismo}
        'content' => 'required|min:6',
        'cover' => 'required|image'
    ]);
Erich García
  • 1,648
  • 21
  • 30
1

I use the same rule for create and update. But for update, I need it to ignore self.

This is what I use:

public function rules()
{
    return [
        'email' => [
            'required',
            'email',
            Rule::unique('users')->ignore($this->user->id ?? 0),
        ],
        // ...other fields
    ];
}

If update, then $this->user->id will be ignored. Otherwise if it's create, it will ignore id 0, which doesn't exist anyway.

Christhofer Natalius
  • 2,727
  • 2
  • 30
  • 39
1

It'll work...

$this->validate($request, 
    [
        'name' => 'required|unique:your_table_name,column_name,'.$request->auto_increment_id
    ],
    [
        'name.required' => 'Name should not be empty',
        'name.unique' => 'Name Already Exists'
    ]
);
1

you can try like this with check if deleted at column is null or not

for example:

$this->validate($request, [
  'email' => 'required|string|max:255|unique:table_name,email,'.$request->id.',id,deleted_at,NULL'
]);
MJ DEV
  • 686
  • 1
  • 11
  • 31
1

This worked for me on Laravel 8.

use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Validation\Rule;

class UserRequest extends FormRequest
{
    public function authorize()
    {
        return true;
    }

    public function rules()
    {
        return [
            'name' => 'required|string',
            'email' => [
                'required',
                'email',
                Rule::unique('users', 'email')->ignore($this->user)
            ]
        ];
    }
}
David Rios
  • 377
  • 4
  • 9
1

This is other solution, pay attention over route parameter, is the "id" of user. Compare with solution mentioned by Arian Acosta.

Route:

Route::patch('users/{id}', [UserController::class, 'update']);

Controller:

public function update(UserRequest $request, $id) 
{
    // ...
}

Form Request:

class UserRequest extends FormRequest
{
    public function rules()`
    {
        return [
            'name' => 'required|string',
            'email' => 'required|email|unique:users,email,'.$this->id.',id',
        //...
        ];
    }
    //...
}
1
    'phone' => 'string|required|max:11|min:11|unique:users,phone,'.Auth::user()->phone.',phone'
ovo
  • 61
  • 3
1

For my case. I am using laravel 10 and I had the same issue. My table name was suppliers, and here is how I setup the rules for the request

'supplier_name' => 'required|string|max:20',
'supplier_company' => 'required|string|max:25',
'supplier_telephone' => 'required|string|max:13',
'supplier_email' => 'required', 'email',Rule::unique('suppliers')->ignore($supplier->id),
OBrien Evance
  • 704
  • 5
  • 18
0

i normaly make a rules array on controller construct, like this:

public function __construct()
{
    $this->rules = [
    'name' => 'required',
    'isCPNJ' => 'required',
    'CPF_CNPJ' => 'required',
    'password' => 'sometimes',
    'role_id' => 'sometimes',
    ];
 }

And then, when i need to validate somenthing specific, like the id and email on update, i create a specificRules variable and concatenate the id that i wish to ignore in the end of the rule,like this:

//Add the original rules to specificRules, just to make things more readable
$specificRules = $this->rules;
//Add the new rules
$specificRules['email'] = 'required|email|unique:users,email,' . $request['id'];
$specificRules['id'] = 'required|exists:users';
//Validate and save in $postData
$postData = $this->validate($request, $specificRules);

If someone has a more cleaner and simple way, please let me know :D

Carlos Salles
  • 474
  • 2
  • 6
0
  $validator = validator()->make($request->all(), [
            'product_name'  => 'required|min:10|unique:products,name,'.$id,
            'product_slug'  => 'required|min:10|unique:products,slug,'.$id,
            'product_desc'  => 'required',
            'short_desc'    => 'required',
            'color'         => 'required',
            'product_sku'   => 'required|unique:products,sku,'.$id,
            'offer_price'   => 'required',
            'actual_price'  => 'required',
            'product_size*' => 'required',
            'product_image*'=> 'required|mimes:jpeg,png,jpg',
            'product_brand' => 'required',
            'product_meta'  => 'required',
        ]);

    if($validator->fails()) {
        $messages = $validator->messages();
        return redirect()->back()->withErrors($messages);
    }

this $id Forcing a unique rule to ignore a given id this is working for me

MOAZZAM RASOOL
  • 159
  • 1
  • 3