Reputation: 1998
I want 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?
Upvotes: 7
Views: 12723
Reputation: 9329
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.
Upvotes: 6
Reputation: 193
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',
]);
Upvotes: -1
Reputation: 311
My way:
'slug' => $site->slug !== $request->slug ? 'required|min:4|max:80|unique:sites' : 'required|min:4|max:80'
Upvotes: 0
Reputation: 1522
$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.
Upvotes: 0
Reputation: 6544
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 = '[email protected]' 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.
Upvotes: 4
Reputation: 8287
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);
Upvotes: 13
Reputation: 2158
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;
}
}
Upvotes: 0
Reputation: 2400
In your controller methods (store and update) you can use:
$validations = [
'email' => 'required|email|unique:users,email'
];
$this->validate($request, $validations);
Upvotes: -1