Laravel

Learning Laravel: extending Laravel’s Auth workflow without re-coding

Published November 23rd, 2018
Important: The information in this article is over 12 months old, and may be out of date.
But hey, you're here anyway, so give it a read see if it still applies to you.

There’s a project on the horizon and I thought it would be a great candidate for getting my teeth in to Laravel. So I wanted to do some basic ideas that would fit in with how I would need the site to work from both a web perspective as well as an API.

Using Laravel’s super-easy, out-of-the-box Auth makes it effortless. But also, how the heck can I do something extra during the login POST call that is specific to my needs?

I’m a good developer, so editing a core file is just not an option. Ever.

Usually I’d look in to how I can override the method, and then do a simple call back to the parent method to handle the original logic.

But… Laravel’s logic for Auth is extended using traits – in this instance, AuthenticatesUsers. This was a new concept to me – I’d never had to utilise traits for the apps I’ve developed so far. Googling around, I found Simon Hamp’s article on Medium about this very issue – and how to resolve it.

Simon’s article taught me that I cannot override a method from a trait (i.e. good old object-oriented inheritance to extend a base class), but in fact they overwrite the original function – so suddenly that “parent” call is impossible.

Enter using traits and defining aliases. Using the “as” keyword with the trait declaration gives us the ability to rename (or alias) the trait’s methods with a name of our own.

use AuthenticatesUsers
{
    attemptLogin as traitAttemptLogin;
}

This means that I can write a function, using one of the trait’s method definitions (and remember, this overwrites the trait’s method, not override), but given I have defined an alias for the trait’s method, I can use my alias to call the original method.

public function attemptLogin(Request $request)
{
    $response = $this->traitAttemptLogin($request);

    if ($response && Auth::check())
    {
        // when login attempted and Auth is valid
        // do something for my app
    }

    return $response;
}

So in my Controller, I’ve written my own declaration of “attemptLogin”, one of the AuthenticatesUsers trait’s methods.

But because I have the alias defined, I can call the trait’s original method using that alias – traitAttemptLogin.

And boom, this still uses all of Laravel’s effortless Auth code, but still allows me to do something upon successful authentication.

Go and read Simon Hamp’s article on Medium – he does a brilliant job of explaining this (no doubt better than me), and it makes total sense.

The question I have – why is this not listed more commonly?

Googling around for how to extend Laravel’s authentication shows many ways to do it but they do seem more like a “try re-writing it this way” rather than this elegant extension using aliases.

Yet this is a beautiful implementation, and works a treat on Laravel 5.7, nearly 3 years after the original article was written.

This makes me so happy. Base project created, with some related data to play with, and both session-based auth for the web, as well as JWT auth via the API. Structurally I can see how this works beautifully for what the app will need to do. Thank you Simon, you’ve made me a happy camper.

You may be interested in...