If you want to show the number or list of users currently online on your website, there are a few ways to do it. In this tutorial, we will show you two of them.
Notice: To be fair, the most accurate would be to use web sockets and transfer that «live» information with tools like Soketi, but it requires way more configuration. In this tutorial, we went for simple options.
So, our actual goal is to save the last activity of the user. We can achieve it with a built-in Laravel session driver or manually with Middleware.
Option 1: Change the Session Driver to «Database»
Create a sessions
table and migrate the database.
php artisan session:table
php artisan migrate
Update the SESSION_DRIVER
value in the environment file to database
.
.env or in config session.php instead of evp
SESSION_DRIVER=database
Now you can retrieve the total online visitor count:
use Illuminate\Support\Facades\DB; function getOnlineUserCount() { return DB::table(config('session.table'))->count(); }
Retrieve logged-in users:
use App\Models\User; use Illuminate\Support\Facades\DB; function getLoggedInUsers() { return DB::table(config('session.table')) ->distinct() ->select(['users.id', 'users.name', 'users.email']) ->whereNotNull('user_id') ->leftJoin('users', config('session.table') . '.user_id', '=', 'users.id') ->get(); }
Get active users in the last five minutes:
use Carbon\Carbon; use Illuminate\Support\Facades\DB; function getActiveUsersInLastMinutes(int $minutes) { return DB::table(config('session.table')) ->distinct() ->select(['users.id', 'users.name', 'users.email']) ->whereNotNull('user_id') ->where('sessions.last_activity', '>', Carbon::now()->subMinutes($minutes)->getTimestamp()) ->leftJoin('users', config('session.table') . '.user_id', '=', 'users.id') ->get(); }
Option 2: Middleware to Save Last Activity
Add the last_activity
column to the users
table.
php artisan make:migration add_last_activity_column_to_users_table
Schema::table('users', function (Blueprint $table) { $table->integer('last_activity')->index(); });
Do not forget to add the last_activity
value everywhere you create the user.
User::create([ // ... 'last_activity' => now()->getTimestamp(), ]);
And add it into the fillable
array on the User Model:
app/Models/User.php
protected $fillable = [ // ... 'last_activity', ];
Create the UpdateLastActivity
Middleware.
php artisan make:middleware UpdateLastActivity
app/Http/Middleware/UpdateLastActivity.php
namespace App\Http\Middleware; use Carbon\Carbon; use Closure; use Illuminate\Http\Request; use Symfony\Component\HttpFoundation\Response; class UpdateLastActivity { /** * Handle an incoming request. * * @param \Closure(\Illuminate\Http\Request): (\Symfony\Component\HttpFoundation\Response) $next */ public function handle(Request $request, Closure $next): Response { if ($user = auth()->user()) { $user->timestamps = false; $user->last_activity = now()->getTimestamp(); $user->saveQuietly(); } return $next($request); } }
We set $user->timestamps = false
only for this call to keep the updated_at
field untouched. Otherwise, updated_at
and last_activity
will refer to the same time, and technically we are not updating the user.
The user model is saved by calling the saveQuietly
method not to fire any observers registered with the user model with every request. This would be an unwanted side effect.
Finally, register UpdateLastActivity
Middleware.
app/Http/Kernel.php
protected $middlewareGroups = [ 'web' => [ // ... \App\Http\Middleware\UpdateLastActivity::class, ],
Now you can query Users by their activity using Eloquent, disregarding what session driver you use.
User::where( 'last_activity', '>', now()->subMinutes(5)->getTimestamp() ) ->get();