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

Zhekaus's avatar

Auth:check()

Hi guys, Could you explain me why Auth::check() does query to database? This method is devoted to check whether the user is logged in. So, as to me, there is no point to query database checking his id or whatever. What do you think?

0 likes
20 replies
bobbybouwmann's avatar

It will only do that once, take a look at the code in the Guard class

    // If we have already retrieved the user for the current request we can just
        // return it back immediately. We do not want to pull the user data every
        // request into the method because that would tremendously slow an app.
        if (! is_null($this->user)) {
            return $this->user;
        }

        $id = $this->session->get($this->getName());

        // First we will try to load the user using the identifier in the session if
        // one exists. Otherwise we will check for a "remember me" cookie in this
        // request, and if one exists, attempt to retrieve the user using that.
        $user = null;

        if (! is_null($id)) {
            $user = $this->provider->retrieveById($id);
        }

Only the last if statement here checks in the database. So if Auth::check is already used once and the user is set, there won't be any query ;)

1 like
Zhekaus's avatar

Once per what? I see in query monitor that it does it once… for every GET request. It doesn’t matter how many times I call Auth::check() in the GET request, there is only call to the mysql like this:

Prepare   select * from `ec_user` where `ec_user`.`id` = ? limit 1
Execute   select * from `ec_user` where `ec_user`.`id` = '2' limit 1
Close stmt
Quit

However, what is this call for?

pmall's avatar

@Zhekaus when you use auth, well, if you want to use the logged in user you have to retrieve it. There is no problem with this.

bobbybouwmann's avatar

Well take a look at the code again

    $id = $this->session->get($this->getName());

        // First we will try to load the user using the identifier in the session if
        // one exists. Otherwise we will check for a "remember me" cookie in this
        // request, and if one exists, attempt to retrieve the user using that.
        $user = null;

        if (! is_null($id)) {
            $user = $this->provider->retrieveById($id);
        }

We check here is the session has a user id. If it has we retrieve the user by it's id. If the session doesn't have a user id we continue to get the from the cookie.

    // If the user is null, but we decrypt a "recaller" cookie we can attempt to
        // pull the user data on that cookie which serves as a remember cookie on
        // the application. Once we have a user we can return it to the caller.
        $recaller = $this->getRecaller();

        if (is_null($user) && ! is_null($recaller)) {
            $user = $this->getUserByRecaller($recaller);

            if ($user) {
                $this->updateSession($user->getAuthIdentifier());

                $this->fireLoginEvent($user, true);
            }
        }

1 like
jekinney's avatar

By default the auth has the user object when the user logs in. It keeps the object in a session till the user logs out or the session expires.

The only time you'll hit the database after log in is if you chain a relationship to the auth object (auth()->hasRole()). Then it will add that to the session upon retrieval.

Pretty standard among any auth system.

1 like
Zhekaus's avatar

@bobbybouwmann, Sorry for my possibly silly questions! The thing is I’m still a newbie in Laravel, you know. )) So, when the session you are talking about does expire? As I see, Auth::check() calls database server every web request but once. Hence this session starts and expires every single request from the browser, doesn’t?

bestmomo's avatar

@Zhekaus

Look in config/session.php :

'lifetime' => 120,
'expire_on_close' => false,
Zhekaus's avatar

@jekinney I see that you as think as I do. However, I do see in mysql log that every get-request like http://localhost:8000/api/auth/check hits the atabase server as I showed before. Here is my php-code to prove its correctness (I hope, it is):

Route::get('auth/check','Auth\AuthController@Check');
public Function Check()
{
    try {
        if (Auth::check()) {
           return Response::json([
                'id' => Auth::user()->id,
                'name' => Auth::user()->name,
                'role' => 'user',
                'isNew' => \Session::get('isNew', 0)
            ]);
        } else {
            return Response::json
        ['flash' => Authorization error']
            );
        }
    } catch (\PDOException $e) {
        return Response::json(
            ['flash' => 'Database server access error'],
            500
        );
    }
}
Zhekaus's avatar

@bestmomo There is exactly what you print:

    'lifetime' => 120,
    'expire_on_close' => false,
Zhekaus's avatar

Not at all, it doesn’t answer my first question.

The thing is, @bobbybouwmann barely confused me with his answers mentioning sessions. Actually, he said that Auth really does hit a database EVERY request. And I knew that beforehand. I merely don’t understand why is that, for what sake it does it at all.

Actually, you guys explained how Laravel does it once, but no why.

pmall's avatar

@Zhekaus During your request you use Auth.

Auth need to retrieve the logged in user for the db in order to work.

Thats all.

If you do $user = Auth::user(); in order to work with the user object, you need to retrieve it from the db isn't it ? So thats all. It is like you were saying, on each page I want to display a post object but why do I have to select the post object everytime.

Stop overthinking small things like this and have fun.

1 like
Zhekaus's avatar

@pmall Sorry for being so restless. User object should be retrieved when the user isn’t logged in yet or his session is already expired. However, Laravel does it every request which checks authentication, even if the user is perfectly logged in, session is alive and there is no need to retrieve any new information from database.

I expected to get an answer revealing and explaining some kind of security or architectural issues. However you merely answer me “It’s normal, stop think about it ” ;-) But I can’t stop thinking, because it can lead to performance issues.

pmall's avatar

I dont understand why do you expect the user info shoudlnt be selected from the database if he is logged in. Where do you expect its data to come from ?

And no, there is no performance issue with this.

Zhekaus's avatar

@pmall Of coutse, it had to be selected from the database at the moment, when the user is logging in. But it shouldn't be selected again and again when I simply want to check whether the user is still logged in and his session isn't expired.

bobbybouwmann's avatar

Laravel does that so you can always access the user object. If you would only check the session this wouldn't work. Unless you would store the complete user object in the session. But that doesn't work either because you might update your name and then the session wouldn't be updated.

Now as a use case take your menu for an example, let's display the username and email (we only use one query here, which is perfectly fine)

@if (Auth::check()) // First query
    <li class="username">{{ Auth::user()->username }}</li> // No query
    <li class="email">{{ Auth::user()->email }}</li> // No query
@endif  
pmall's avatar
pmall
Best Answer
Level 56

So it is doing it because the user id is stored in session. When Auth::check() the user is retrieved from this id, and it makes sense : let say you ban this user and delete it from the db, he still have its id in session. You have to check if it is a legitimate user otherwise he could still use the website until his session is expiring.

If you don't like this it I dont know what to say. Really it shouldnt matter.

1 like
Zhekaus's avatar

@pmall Thank you for your response. It makes sense.

And btw, I do have a performance issue with this right now on my developers computer. Yesterday I noticed that Livereload reloads pages seemingly slow and it started hindering. I started looking for the reason and discovered that it was because of slowing down mysql server. It was strange because my template didn’t load anything from the database and the user was already logged in. Absolutely, in product environment the picture will be different. But I bother anyway.

Zhekaus's avatar

@bobbybouwmann ,

Thus Laravel makes user object to be actual in every secured request. It makes sense if it can be changed directly in the database.

I believed that I could control it by my own. However, Laravel doesn’t give me such an option.

lukegalea16's avatar

Is it possible to grant access to users which do not exist in the DB?

Please or to participate in this conversation.