Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

Devon's avatar
Level 18

Log in with username or email in Laravel 5...

How would I let users log in using either their username or email from a single input field in Laravel 5?

Using a Request, the data gets validated upon method injection. In L4, I would detect if the input matched the regex of an email and then manually set it as the field to be validated. How would something like this be accomplished in L5?

0 likes
32 replies
afrayedknot's avatar

Easy - just have a required field for your username in the validation


return [ 'username' => 'required', 'password' => 'required', ];

Then in your AuthController check it against the username or email field:


if (Auth::attempt(['username' => $request->username, 'password' => $request->password])) { echo "success with username!"; } elseif (Auth::attempt(['email'=> $request->username, 'password' => $request->password])) { echo "success with email!"; } else { echo "fail!"; }
3 likes
Devon's avatar
Devon
OP
Best Answer
Level 18

Thanks, I managed to figure it out in a similar fashion.

public function rules()
{
    return [
       'login' => 'required',
       'password' => 'required'
    ];
}
public function login(LoginRequest $request)
{
    $field = filter_var($request->input('login'), FILTER_VALIDATE_EMAIL) ? 'email' : 'username';
    $request->merge([$field => $request->input('login')]);

    if ($this->auth->attempt($request->only($field, 'password')))
    {
        return redirect('/');
    }

    return redirect('/login')->withErrors([
        'error' => 'These credentials do not match our records.',
    ]);
}
18 likes
kaju74's avatar

Any way to translate "These credentials do not match our records" w/o changing the vendor source files?

bashy's avatar

Extend it and enter your own message.

kaju74's avatar

Thank you. Okay, so I create a new class extended from the base one and use this as my instance? Sorry, it my question is stupid, but I'm a very new beginner ;-) Does the core of Laravel will be easier translateable in the future? Why does the core doesn't make use of the language folder and the @lang-feature?

bestmomo's avatar

For message there is now a function in AuthenticatesAndRegistersUsers trait :

/**
* Get the failed login message.
*
* @return string
*/
protected function getFailedLoginMesssage()
{
    return 'These credentials do not match our records.';
}

So you just have to override this function.

4 likes
kaju74's avatar

What's the best way to override a method? Sorry for thuch a stupid question..;-)

kaju74's avatar

Okay - solved it. Due of my beginner status, I'd to learn a lot stuff, so now I know how to override ;-)

Happy easter, kaju

frezno's avatar

wouldn't a

//...
->whereNameOrEmail($request->input('username'), $request->input('email'))
//...

do it as well?
Haven't tried it, just wondering...

scottnelson's avatar

To log in with username instead of email, just add:

protected $username = 'username';

to AuthController.php

where 'username' is the field in your users table.

However, this will replace email with username. To log in with either email or username, (as far as I know) you'll need to override the postLogin() method with your own authentication logic in AuthController.php.

5 likes
andrewtweber's avatar

To avoid rewriting all of the AuthenticatesUsers code, just do this:

use AuthenticatesAndRegistersUsers, ThrottlesLogins {
    AuthenticatesAndRegistersUsers::postLogin as laravelPostLogin;
}

....

public function postLogin(Request $request) {
    $field = filter_var($request->input('login'), FILTER_VALIDATE_EMAIL) ? 'email' : 'username';
    $request->merge([$field => $request->input('login')]);
    $this->username = $field;

    return self::laravelPostLogin($request);
}
6 likes
vedmant's avatar

I used this approach, overloaded two functions:

/**
 * Get the login username to be used by the controller.
 *
 * @return string
 */
public function loginUsername()
{
    return 'login';
}

/**
 * Get the needed authorization credentials from the request.
 *
 * @param  \Illuminate\Http\Request  $request
 * @return array
 */
protected function getCredentials(Request $request)
{
    $login = $request->get('login');
    $field = filter_var($login, FILTER_VALIDATE_EMAIL) ? 'email' : 'username';

    return [
        $field => $login,
        'password' => $request->get('password'),
    ];
}

As for me this looks cleaner.

Another thing I didn't like in laravel is that there is no way to use Validator functions independently, for example in Kohana I could use the same functions from Validation module just like this if (Valid::email('test@test.com')) ... Btw, Kohana supported login by both email and username out of the box.

6 likes
bertog's avatar

@vedmant I've found this thread searching about the same problem. Sorry I'm quite a noob. Overloading the to functions means that this code is put in the AuthController instead on the trait?

Thanks in advance. Guido

vedmant's avatar

@betog Yes, right, you can find this method in AuthenticatesUsers trait but you overload this method with method in your AuthController, cause AuthenticatesUsers is part of Laravel framework, but AuthController if part of your application.

Mohammadsgh's avatar

$field = filter_var($request->input('login'), FILTER_VALIDATE_EMAIL) ? 'email' : 'mobile';

    if (Auth::attempt([$field => $request->login , 'password' => $request->password]))
    {
        return 'You Are Logged in';
    }
Kode's avatar

If you use vedmants way, don't forget to put use Illuminate\Http\Request; at the top

simplenotezy's avatar

I have used this approach and it is fine.

However, what about handling password resets, etc? I see that there is a contract called UserProvider, here: Illuminate\Contracts\Auth\UserProvider. Maybe there is a smart way to change the approach once, and it will be reflected everywhere.

saaz's avatar

Adding protected $username = 'username' in Class AuthController might do the trick

daylight's avatar

The accepted answer on this discussion looks like it completely bypasses the login throttling that comes for free. It would be nice to see an updated solution to this problem.

bryangruneberg's avatar

@bertog - Yeah place that code in the the AuthController. You'll be overriding the methods like that.

I tested this for my app recently, and it works a charm. You do need to remember to call the field in your login form "login" if you want to use the above example directly.

1 like
jes490's avatar

Hi guys!

I'm new here, but I came with this solution (insert this in LoginController):

    protected $username = 'email';

    public function loginNameOrEmail(Request $request)
    {
        $field = filter_var($request->input('email'), FILTER_VALIDATE_EMAIL) ? 'email' : 'name';
        $request->merge([$field => $request->input('email')]);
        $this->username = $field;

        return $this->login($request);
    }

    public function username()
    {
        return $this->username;
    }

Then I just changed my auth routes with this:

Auth::routes();
Route::post('login', 'Auth\LoginController@loginNameOrEmail');

I think this is much cleaner, but maybe I miss something, so far I'm just a newbie.

3 likes
AktherHussain's avatar

Hi guys,

I follow this technique to use default authentication system provided by Laravel.

  1. Change the input field type 'email' to 'text' from login view
  2. Find AuthenticatesUser.php file and replace $credentials = $this->getCredentials($request); to following code.
    if(filter_var($request->input('email'), FILTER_VALIDATE_EMAIL)){
            $credentials = $this->getCredentials($request);
        } else {
            $credentials = [
                'username' => $request->input('email'),
                'password' => $request->input('password')
            ];
        }

That's all to login with username or email using laravel default auth.

jes490's avatar

When u run composer update there is a chance that your code will be rewritten by framework, so don't modify vendor code, override whole method.

ajayagrahari's avatar

We can write the where clause with callbacks to check wheather user exist on their username or email with their passwords. Best solution i found from :

Login with username or email in Laravel 5


->where(function($q) user($request){
    $q->where('username',$request->search)
       ->orWhere('email',$request->search);
});

1 like
arabsight's avatar

I think the cleanest way is to override the username method:

// LoginController

public function username()
    {
        $login = request()->input('login');
        $field = filter_var($login, FILTER_VALIDATE_EMAIL) ? 'email' : 'username';
        request()->merge([$field => $login]);
        return $field;
    }
2 likes
twady77's avatar

This works fine for me: In Laravel 5.4 By default, Laravel uses the email field for authentication. If you would like to customize this, you may define a username method on your LoginController(found in app\Http\Controllers\Auth):

public function username() { return 'username'; }

Then, set your input type to text in your form/blade - for instance:

1 like
Bagmaz's avatar

Hi, in Laravel 5.5 its easy

protected $redirectTo = '/profile'; // option

/**
 * Create a new controller instance.
 *
 * @return void
 */
public function __construct()
{
    $this->middleware('guest')->except('logout');
}

public function username()
{
    $field = filter_var(request()->input('login'), FILTER_VALIDATE_EMAIL) ? 'email' : 'username';
    request()->merge([$field => request()->input('login')]);
    return $field;
}
grafix's avatar

@Bagmaz, It didn't work on mine. I did some research and I found this working on the latest version of laravel. I only tried the name of the user since I'm still studying laravel. My future plan uses this method on all users(admin, guest, superadmin). I tried to put the function inside the controller I guess it the base controller that inherits all the controller on different users. But there's no luck at all.

   protected function credentials(Request $request)
    {
        $field = filter_var($request->get($this->username()), FILTER_VALIDATE_EMAIL)
            ? $this->username()
            : 'name';

        return [
            $field => $request->get($this->username()),
            'password' => $request->password,
        ];
Next

Please or to participate in this conversation.