php - Laravel validation rule: unique with additional condition

In my Laravel application, in the users table I have an additional column named platform.

When new users sign up, they pick one of three platforms: site1, site2, site3. Now, I want to validate that the entered email is unique, but only for the selected platform.

For example, let's say a user exists with email = john@doe.com and platform = site1.

Then, if you go to the register form and input...

email = john@doe.com
platform = site2

...you should be able to sign up.

But if you enter...

email = john@doe.com
platform = site1

...you should see an error message because the user john@doe.com already exists for the platform site1.

In my validator, I've been unable to set this up. If I do this then it returns an error even when platforms are different (as expected):

Validator::make($request->all(), [
    'email' => ['required', 'unique:users'],
]);

But if I do this, in an attempt to group the unique condition by platform, then all signups are allowed even when platforms are the same:

Validator::make($request->all(), [
    'email' => ['required', 'unique:users,platform,site1'],
]);

Is there a way to set this up?

Answer

Solution:

You can specify where conditions in the unique rule.

'email' => [
   "required",
   Rule::unique('users')->where(fn ($query) => $query->where('platform', request()->platform)), //assuming the request has platform information
];

And, to ensure uniqueness at the database level, you might want to define the email and platform as a composite unique key

In the migration:

$table->unique(['email','platform']);

Reference: https://laravel.com/docs/9.x/validation#rule-unique under the headline: Adding Additional Where Clauses:

https://laravel.com/docs/9.x/migrations#creating-indexes to get more information about creating composite indexes in Laravel.

Advice: RTFM

Source