DEV Community


Laravel — knowing when your users were last online

mattkingshott profile image Matt Kingshott 👨🏻‍💻 Originally published at on ・3 min read

Laravel — knowing when your users were last online

This article is part of a series where I document insights, changes and rethinking that I experienced while refactoring the codebase for Pulse — a painless and affordable site & server monitoring tool designed for developers.

Today, I’m going to talk about how I added middleware functionality to record when a user was last online / using the app. I wanted to add this to Pulse for some analytical questions I needed answering.

Preparing the database

If we want to record when a user was last online, then we’re going to need to add a timestamp to the users table for that purpose. That’s an easy step, so we’ll begin with that. Insert the following into your users table migration:

Enter fullscreen mode Exit fullscreen mode

Next, we want Laravel to recognise this attribute as a Carbon instance so that we can take advantage of its extensive date and time feature set. So, within our User model class, we’ll add it to the $casts array:

class User
    protected $casts = ["last_online_at" => "datetime"];
Enter fullscreen mode Exit fullscreen mode

Adding the logic to the application

Since we want to be able to set / update this value from any potential entry point into the app, the ideal place to store the logic is within a middleware class. So, let’s go ahead and create one:

namespace App\Http\Middleware;

use DB;
use Closure;

class LastOnlineAt
    public function handle($request, Closure $next)
        if (auth()->guest()) {
            return $next($request);

        if (auth()->user()->last_online_at->diffInHours(now()) !== 0)
              ->where("id", auth()->user()->id)
              ->update(["last_online_at" => now()]);

        return $next($request);
Enter fullscreen mode Exit fullscreen mode

There’s quite a bit going on here, so let’s break it down…

  1. First, we check if the user is a guest. If so, we continue on as we can’t set a timestamp for a guest user.
  2. If the user is authenticated, we retrieve their last online timestamp.
  3. Next, we determine if this timestamp is more than an hour old (this is a check I added to avoid updating the database on every request, but you could set this check to whatever you want, or remove it entirely).
  4. Assuming the time difference exceeds one hour, we update the timestamp in the database with the current time.
  5. Regardless of whether step 4 was performed, we then continue with the user’s request (whatever it might be).

You may be wondering why I didn’t just update the authenticated user directly instead of using the DB facade?

Well, if we update the model itself, that would cause it to fire events and also set the updated_at timestamp to the current time as well. Technically the user record hasn’t actually been updated as such, we’ve just set the time they were last online. As a result, I think using the DB facade is a better option.

The final step

All that remains, is for us to instruct Laravel to use the middleware. We do this within the HTTP kernel of application. Simply add the class to the web and api arrays within the $middlewareGroups property e.g.

protected $middlewareGroups = [
    "web" => [LastOnlineAt::class],
    "api" => [LastOnlineAt::class],
Enter fullscreen mode Exit fullscreen mode

Now whenever an authenticated user visits a web or api route, Laravel will set their last_online_at timestamp. Neat!

Wrapping Up

I have more articles to share, so if you’re interested in reading them, be sure to follow me here on Medium. You can also follow me on Twitter.

Lastly, if you’re in the market for an affordable and painless site & server monitoring tool that doesn’t require you to have a DevOps degree, please take a moment to check out Pulse. I think you’ll find it to a be a breath of fresh air!

Thanks again and happy coding!

Discussion (2)

Editor guide
efroim102 profile image
Efroim Rosenberg • Edited

You might have a bug in the code seeing as the $user variable is never being set.

You probably meant auth()->user()->last_online_at.

mattkingshott profile image
Matt Kingshott 👨🏻‍💻 Author

Well spotted. Fixed. Thanks!