Question

I'm having trouble figuring out how I can count the number of logged-in users in my application.

What I have: When a user logs in, they get a session (which is used when the user wants to visit a protected page) and the IsLoggedIn column for the user in the users table is set to 1 to indicate that the user is logged in. When the user logs out, the value is set back to 0. Counting the number of 1s in the users table makes it easy to return the number of users logged-in. But...

The Problem: If the user closes the browser without logging out, the value in the database stays 1, indicating that the user is still logged in even though their session has ended when they closed the browser.

Question: Could some one suggest a proper way of doing this?

Was it helpful?

Solution

Rather than a IsLoggedIn column, you should add a LastTimeSeen column. Any time a person visits a page you update the column:

UPDATE members SET LastTimeSeen = NOW() WHERE id = $the_user_id

Then to get how many people are on the site at any given moment you use the query:

SELECT COUNT(*) FROM members WHERE LastTimeSeen > DATE_SUB(NOW(), INTERVAL 5 MINUTE)

That shows how many people have viewed a page in the past 5 minutes, which is the best you're gonna get without a much more complicated solution.

OTHER TIPS

Just to offer another solution:

if ($user->isLoggedIn()) {
  touch("/writable/path/loggedInUsers/" . $user->id);
}

If you don't need to query this data, a local file touch is far faster than a DB write. To get logged in users, scan the directory for filemtimes under N seconds old.

Because of the way our site is constructed, it was necessary to use the ajax approach. I'm using jQuery so it's relatively painless.

These lines went into the $(document).ready function.

fnShowImOnline();
setInterval('fnShowImOnline', 120000);

This is the javascript function...

function fnShowImOnline() {
    $.get('ajax/im_online.php');
}

And here is the PHP

<?php
    session_start();
    if ((isset($_SESSION['user']))&&($_SESSION['authorized']=='authorized')) {
        include('../includes/db.php');
        db_connect();
        mysql_query("UPDATE members SET last_checked_in = NOW() WHERE user_id = {$_SESSION['user']['user_id']}");
    }

?>

The count is straight PHP/mySQL.

//  Members online.
$online_sql = "SELECT COUNT(*) FROM members where last_checked_in > DATE_SUB(NOW(), INTERVAL 5 MINUTE)";
$online_RS = mysql_query($online_sql);
$online_row = mysql_fetch_row($online_RS);
$online = $online_row[0];

For those times I need to update the numbers dynamically, this bit of ajax does the trick.

$.ajax({
    url: 'ajax/members_online.php',
    dataType: 'json',
    success: function(response) {
        if (!isNaN(response.total)) {
            $('#OnlineTotal').html(response.total + " Total ");
            $('#OnlineOnline').html(response.online +  " Online Now");
        }
    }
})

using this for the PHP/mySQL

//  Members online.
$online_sql = "SELECT COUNT(*) FROM members WHERE last_checked_in > DATE_SUB(NOW(), INTERVAL 5 MINUTE)";
$online_RS = mysql_query($online_sql);
$online_row = mysql_fetch_row($online_RS);
$online = $online_row[0];
//  Members total.
$total_sql = "SELECT COUNT(*) FROM members";
$total_RS = mysql_query($total_sql);
$total_row = mysql_fetch_row($total_RS);
$total = $total_row[0];
$response = json_encode(array('total'=>$total,'online'=>$online));
echo($response);

This is working well for us.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top