简体   繁体   中英

Laravel request update unique field only if changed

I wan't to be able to validate a user email address based on certain circumstances.

For example

If a user is being created, the email address must be unique

If a user is being updated but the email address hasn't changed, ignore the unique email rule

If a user is being updated and their email address has changed, it has to be unique

I've had a little look around and I know that I can specify different rules based on the method like so

public function rules()
{
    $user = User::find($this->users);

    switch($this->method())
    {
        case 'POST':
        {
            return [
                'user.email'      => 'required|email|unique:users,email',
            ];
        }
        case 'PUT':
        case 'PATCH':
        {
            return [
                'user.email'      => 'required|email,
            ];
        }
        default:break;
    }
}

Is there any way to make it so that in the put/patch case, the rule checks if the email address has been changed, and if it has then it has to be unique?

If not is there a cleaner way of achieving this goal? Maybe without the switch case? Perhaps more in depth validation rules I haven't stumbled across yet?

If i understand you correctly, you want to add unique validation if email changed, if that is the case then you just need to add a condition in validation. If you check unique validation structure it look like this unique:table,column,except,idColumn , check documentation

So the validation will be look like this, when you will create new record $userId will be null but at time of patch it will have value. So this validation will work for both create and patch.

$userId = isset($user) ? $user->id : null;

$rules = [
        'email' => 'required|email|unique:users,email,'. $userId.',id',
    ];

 $this->validate($request, $rules);

There is a built-in feature for this. You can add the actual user id to the unique constraint, if present. This will ensure that the unique constraint will still work, but it will not fail when the value did not change:

$exists = $user->exists;
$rules = return [
    'user.email' => 'required|email|unique:users,email' . ($exists ? ','.$user->id : ''),
];

Internally, this will execute a query like:

SELECT count(id) FROM users WHERE email = 'some-mail@example.com' AND id != 42

The latter part AND id != 42 will only be part of the query when you add the third parameter to the unique validation rule.

I had a similar issue and found a tidy way of addressing it in the docs.

My issue was that if a user was already created, the email address claimed it wasn't unique, even if it was already registered to the user.

https://laravel.com/docs/8.x/validation#rule-unique

A few headings down is something like this:

use Illuminate\Validation\Rule;

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

This does the following:

Validate the email address, make it required and unique, unless the user ID of that row matches this user.

You are missing the break; statement after every case. And for Update (PATCH request) you have to pass id also in update request.

public function rules()
{
    $user = User::find($this->users);

    switch($this->method())
    {
        case 'PATCH':
        {
            return [
                'user.email'      => 'required|email|unique:users,email,'. $user->id.',id',
            ];
        }
        break; // change here
        case 'PUT': break; // change here
        case 'POST':
        {
            return [
                'user.email'      => 'required|email,
            ];
        }
        break; // change here
        default:break;
    }
}
$request->validate([
        'naam' => 'required|max:190|unique:database_name.table,column_where_you_check_unique,'.$id.',$id_column_reference'
    ]);

'naam' - form input field name

database_name(optional) - if you have multiple database

table(required) - table name

column_where_you_check_unique(required) - where data is unique

$id(required) - check with id autoincrement

$id_column_reference - column name of $id.

我的方式:

'slug' => $site->slug !== $request->slug ? 'required|min:4|max:80|unique:sites' : 'required|min:4|max:80'

In your controller methods (store and update) you can use:

 $validations = [
        'email'                 => 'required|email|unique:users,email'
    ];

 $this->validate($request, $validations);

You can try this

$exists = Section::where('code', $request->code)->exists();
        $isUpdateQuery = (($request->method() == 'PUT') || ($request->method() == 'PATCH'));
        $validatedData = $request->validate([
            "code" => ['required','unique:sections,code' . (($isUpdateQuery && $exists) ? ',' . $request->code . ',code': '')],
            "title" => 'required | json',
            "subtitle" => 'required | json',
            "btn_title" => 'required | json',
            "name" => 'required',
            "pageID" => 'required | exists:pages,pageID',
            "image" => 'nullable',
            "btn_link" => 'nullable',
        ]);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM