Laravel unique email validation is not working on different character case in mongodb
Asked Answered
C

5

5

I have a registration form with unique email validation. When I enter different character case, emails does not apply unique validation.

[email protected], [email protected], [email protected]: Laravel unique validation is failed.

[email protected], [email protected], [email protected]: Laravel unique validation is success.

Please check my code below and correct me. Email is storing as lowercase in database.

DB - Mongodb,

Framework - Laravel 5.5

jenssegers/laravel-mongodb is using to connect laravel and mongodb

RegisterController.php

protected function validator(array $data)
{
  return Validator::make($data, [
     'firstName' => 'required|string|max:255',
     'lastName' => 'required|string|max:255',
     'email' => 'required|string|email|max:255|unique:user,usrEmail',
     'password' => 'required|string|min:6|confirmed',
  ]);
}

User.php (Model)

public function setusrEmailAttribute($value)
{
  $this->attributes['usrEmail'] = strtolower($value);
}
Cartography answered 9/2, 2018 at 12:1 Comment(9)
Try use only 'email' => 'required|email|unique:user,usrEmail',Pluvial
@Pyton, Not workingCartography
Try also convert $data['email'] to lowercase. Maybe this is a problem with case sensitive.Pluvial
Do you have a users table or a user table?Shiftless
@Pluvial I have already applied laravel feature mutators so, when user register email will store as lowercase.Cartography
@OluwafemiSule I am using user tableCartography
check last post. github.com/laravel/framework/issues/9430Zolazoldi
@MustafaToker I tried but it's not working. I resolved this issue with laravel custom validation ruleCartography
Take your validations in a request file (( oop alert))Granddad
C
6

With the help of laravel custom validation rule I resolved this issue.

I create a new rule using php artisan command php artisan make:rule Lowercase and defined the rule.

app/Rules/Lowercase.php

public function passes($attribute, $value)
{
 return strtolower($value) === $value;
}

public function message()
{
    return 'The :attribute must be lowercase.';
}

I have attached the rule object with other rules

RegisterController.php

use App\Rules\Lowercase;
protected function validator(array $data)
{
        return Validator::make($data, [
            'firstName' => 'required|string|max:255',
            'lastName' => 'required|string|max:255',
            'email' => [ 'required', 'string', 'email', 'max:255', 'unique:user,usrEmail', new Lowercase ],
            'password' => 'required|string|min:6|confirmed',
            'dataProtection' => 'required',
            'termsService' => 'required',
        ]);
}

While registration users enter email, system will alert the users to use lowercase.

It works for me I am not sure this a good approach or not.

Cartography answered 12/2, 2018 at 11:59 Comment(2)
I don't see the point in requireing the user to set his email lowercase.. however, we might do this automatically in the client js.Encephalo
This is exactly what I needed. Thank you. By doing it this way, it enforces it before the user gets their account into the system. So the user will know what to expect. 🙌Compony
P
3

You may use strtolower($data['email']) before validation.

RegisterController.php

protected function validator(array $data)
{
    $data['email'] = strtolower($data['email']);
    return Validator::make($data, [
        'firstName' => 'required|string|max:255',
        'lastName' => 'required|string|max:255',
        'email' => 'required|string|email|max:255|unique:user,usrEmail',
        'password' => 'required|string|min:6|confirmed',
    ]);  
}
Pamphleteer answered 17/2, 2018 at 10:55 Comment(0)
A
3

I know you already closed this out but I did want to propose two possible alternative solutions.

Form Request Validation: After Hooks

For this approach you would create a custom form request (like you did) and do something like this:

/**
 * Configure the validator instance.
 *
 * @param  \Illuminate\Validation\Validator  $validator
 * @return void
 */
public function withValidator($validator)
{
    $validator->after(function ($validator) {
        if ($this->somethingElseIsInvalid()) {
            $validator->errors()->add('field', 'Something is wrong with this field!');
        }
    });
}

In here you would be able to cast the email to lowercase and compare it with your database. This way you don't have to rely on the user reentering the email. You only have to go back to the user with an error if the email is not unique. In short, this allows you to perform extra validation.

Middleware?

The second way, and probably not the right way, would be using a custom Middleware. I don't see a reason why you couldn't setup something like this:

<?php

namespace App\Http\Middleware;

use Closure;

class CheckEmail
{
    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @return mixed
     */
    public function handle($request, Closure $next)
    {
        if ($this->someIsUniqueChecker($request->email)) {
            return redirect()->back()->withErrors($someErrors);
        }

        return $next($request);
    }
}

The advantage of using Middleware would be that you will know if the email entered is unique before it hits your validation. Some things to consider!

Asshur answered 18/2, 2018 at 3:49 Comment(0)
J
0

I have the simplest solution to fix unique email issue in MySql in Laravel

Just make your field unique by using below query:

ALTER TABLE `users` ADD UNIQUE(`email`);

This solved my case-sensitive and unique issue, did not need to make any changes in any controller and model scripts. Thanks to ask this question.

Juryrigged answered 8/2, 2020 at 12:43 Comment(0)
R
0

You can simply add couple of lines before the validation

$request->merge([
'email' => strtolower($request->email)
]);
Ralaigh answered 24/7 at 11:7 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.