简体   繁体   中英

Find out how many users are online in PHP?

Every visit to my website updates a user's individual hit counter and updates a column for time() based on their ip address and id stored in a cookie. So when coming to output the data, what's a more efficient way of my following code with less database calls, as it's essentially a copy of itself:

<?
$last1Min = time()-60;
$last5Mins = time()-300;
$last1Hr = time()-6000;
$last1Dy = time()-144000;
$last1Wk = time()-1008000;
$last1Mnth = time()-30240000;

//last1Min
$sql = "SELECT COUNT(*) FROM usersonline WHERE lastOnline > $last1Min";
while($rows = mysql_fetch_array(mysql_query($sql))) {
    echo "Users online in the last minute: " . $rows['COUNT(*)'] . "<br />\n";
}

//last5Mins
$sql = "SELECT COUNT(*) FROM usersonline WHERE lastOnline > $last5Mins";
while($rows = mysql_fetch_array(mysql_query($sql))) {
    echo "Users online in the last 5 minutes: " . $rows['COUNT(*)'] . "<br />\n";
}

//last1Hr
$sql = "SELECT COUNT(*) FROM usersonline WHERE lastOnline > $last1Hr";
while($rows = mysql_fetch_array(mysql_query($sql))) {
    echo "Users online in the last hour: " . $rows['COUNT(*)'] . "<br />\n";
}

//last1Dy
$sql = "SELECT COUNT(*) FROM usersonline WHERE lastOnline > $last1Dy";
while($rows = mysql_fetch_array(mysql_query($sql))) {
    echo "Users online in the last day: " . $rows['COUNT(*)'] . "<br />\n";
}

//last1Wk
$sql = "SELECT COUNT(*) FROM usersonline WHERE lastOnline > $last1Wk";
while($rows = mysql_fetch_array(mysql_query($sql))) {
    echo "Users online in the last week: " . $rows['COUNT(*)'] . "<br />\n";
}

//last1Mnth
$sql = "SELECT COUNT(*) FROM usersonline WHERE lastOnline > $last1Mnth";
while($rows = mysql_fetch_array(mysql_query($sql))) {
    echo "Users online in the last month: " . $rows['COUNT(*)'] . "<br /><br />\n";
}

If there is a more efficient way of presenting this data, I'm wanting to extend it to show not only how many users for each of these metrics is online on my entire site, but record and output the data for every page on my site.

SELECT 
  SUM(lastOnline <= 60) AS one_minute,
  SUM(lastOnline <= 300) AS five_minutes,
  ...
  SUM(lastOnline <= 30240000) AS one_month
FROM usersonline

Using this method, you can get everything you need in a single query with a single table scan; it doesn't get much more efficient than that. As others have mentioned, you should cache the result, as it's relatively expensive (even in this optimized form). There's no point in calculating this on every page load, especially if you're seeing multiple hits per second (which is extremely likely if you, say, hit the front page of digg)

lastOnline <= 60 evaluates to 1 for rows where the condition is true, and 0 for rows where the condition is false; SUM() sums these 1s and zeros, giving you a count of the number of rows for which the condition is true.

Learned this technique from a user comment in the mysql docs a few years ago; there are similar examples elsewhere

Set up a cron job that calculates the correct values only once every minute/5 minutes/etcetera. Cache the result and display that instead. There's really no need to calculate these kinds of stats X times a second when they only change once a minute or once ever half hour.

Instead of calling the database for each of the times you could just make a call for all within the last month and order them by date. Then in php you can compare the date and time to see how long ago the user last logged in.

If you save your sessions to files, you could count the number of files that have been accessed in a time period. Then there'd be no database access at all.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM