10

I'm building a community website. Users will login and logout as usually.

I use the attribute status online/offline to set the user's status. But what if a user just clicks the X button or disconnects otherwise without logging out?

Lately my computer crashed, when I opened the site with my laptop I could not login because I don't allow login in two places. I go to PHPMyAdmin and I see my status still online. Is there any fix for this.

I tried the last_time activitiy thing but that doesn't work in case of a computer crash! And there was nothing neither interactivity or refresh to update the table.

neophyte
  • 6,540
  • 2
  • 28
  • 43
aygeta
  • 429
  • 3
  • 7
  • 17

12 Answers12

21

You don't need the online/offline flag, you just need to save the last activitity time. When displaying the user status, if last activity time is less than now+15 minutes then user is online, offline otherwise.

4
CREATE TABLE `user_online` (
`session` char(100) NOT NULL default '',
`time` int(11) NOT NULL default '0'
) TYPE=MyISAM;

<?php

session_start();
$session=session_id();
$time=time();
$time_check=$time-600; //SET TIME 10 Minute

$host="localhost"; // Host name
$username=""; // Mysql username
$password=""; // Mysql password
$db_name="test"; // Database name
$tbl_name="user_online"; // Table name

// Connect to server and select databse
mysql_connect("$host", "$username", "$password")or die("cannot connect to server");
mysql_select_db("$db_name")or die("cannot select DB");

$sql="SELECT * FROM $tbl_name WHERE session='$session'";
$result=mysql_query($sql);

$count=mysql_num_rows($result);

if($count=="0"){

$sql1="INSERT INTO $tbl_name(session, time)VALUES('$session', '$time')";
$result1=mysql_query($sql1);
}

else {
"$sql2=UPDATE $tbl_name SET time='$time' WHERE session = '$session'";
$result2=mysql_query($sql2);
}

$sql3="SELECT * FROM $tbl_name";
$result3=mysql_query($sql3);

$count_user_online=mysql_num_rows($result3);

echo "User online : $count_user_online ";

// if over 10 minute, delete session
$sql4="DELETE FROM $tbl_name WHERE time<$time_check";
$result4=mysql_query($sql4);

// Open multiple browser page for result


// Close connection

mysql_close();
?>
Sun Love
  • 744
  • 5
  • 9
4

Because of the nature of the web, you can't know when a user disconnects, yanks the cable or shuts down his computer without politely telling you.

You could have a script (AJAX) check every X minutes to see if the browser still responds, and if not, toggle offline - but that would consume extra resources. This is how for example an IRCd works: they PING you, you PONG back. If you don't pong back, you timeout and get disconnected from the server.

HTTP is stateless, there is no other built-in solution. Maybe HTML5 and sockets, but that would be the same principle as just plain AJAX.

Konerak
  • 39,272
  • 12
  • 98
  • 118
  • So now there is nothing i cant do. I just can sit there and watch my users get angry :) This is bad. How can i implement this with ajax ? Isnt this method still depending on whether the user has interaction with the site. Isnt this javascript side of coding ?If so the user must access my site to do interaction with ajax :) – aygeta Nov 06 '11 at 10:20
  • You implement the 'last time seen less than X minutes' feature. That works. Now, to increase the reliability of the feature, decrease X, and force the users to interact each X/2-(1ms), using for example AJAX. – Konerak Nov 06 '11 at 10:26
  • The answer marked as correct offers a practical solution contrary to your statement – zardilior Jul 21 '16 at 19:32
1

You can use this method 1. check user status if it is online check last activity if it is more than 10 min set status to offline if it is less than 10 min show till user online if it is off line show user offline

  1. When user using this site update last activity in every "x" min with ajax
  2. When user click on logout set status to off line. This could be your database structure.

enter image description here

Sandeep
  • 1,504
  • 7
  • 22
  • 32
1

You can run a function on each page request that updates a row in your database with your user's ID and a calculated timestamp for the future (e.g. time()+(60*5); - five minutes). Then whenever another user attempts to check if the first user is online, you can check it against the database using a 'pulse' check:

$time = time();
$query = mysql_query("SELECT user_id, timestamp FROM online_users WHERE user_id = '$user_id' AND timestamp > '$time'");

If this query returns more than 0 rows, the user is considered online.

Seralize
  • 1,117
  • 11
  • 27
1

Farfetched solution.

Use a node.js server with socket.io. Have the client connect to the server via the socket.io client side. The server is responsible for emitting events to the clients and expecting a response. On disconnect or late response mark the user offline.

It will work and probably will be working even on cable disconnects/browser closing but is it worth the effort?

mobius
  • 5,104
  • 2
  • 28
  • 41
0

wait man, i think i have the right reply because i did faced the same problem ! try to use the mouse event [click,movemouse ..] but with a delay to not creat a crash in the navigator, you will use setInterval on a xx sec or minutes after you save the event reply to your db in the activity column but with unix time in order to differentiate it later to the now time .. its useful really, i used it to log members acitvity to know what they really do in real time and get the online/offline users too. here is the used js functions:

var body = document.getElementById('body');
var url = './member-activity.php?loggedUser=<?=$memb_id?>&curl=<?=($_SERVER['QUERY_STRING'])?>';
if(document.addEventListener) {
  document.addEventListener("click", _EventLogging, false);
    document.addEventListener("mousemove", _EventLogging, false);
}else{
  document.attachEvent("onclick", _EventLogging);
}
function _EventLogging(){
//call it after a delay of 
setTimeout(AjaxUrl(url), 2000); //delay of 2 sec after every move of cursor
}
//AjaxUrl is a js function that calls a php file to perform the activity logging via AJAX
</script>
<div id="id"></div>

the div above is to notify you about errors in code, u remove it when its ok! i hope that my answer was right for ur case //dr.alpha@hotmail.co.uk

0

Well the real answer for ur question "How will i update the table without user interaction ?"

is MySql event scheduler , you schedule a an event (query) to be executed at whenever you wish even if the user is OFFLINE , read about it here (http://dev.mysql.com/doc/refman/5.1/en/events-overview.html)

EvilThinker
  • 740
  • 1
  • 9
  • 13
0

actually the only accurate way to do that is using websocket, it will communicate with the user with real-time communication, try Ratchet.

shamaseen
  • 2,193
  • 2
  • 21
  • 35
0

You're on the right path: save user's last activity's UNIX time in the database, and, when someone accesses the site, set the offline status for users that were not active for 15 minutes (or less). If the user is logged in and his status is set to offline in the database, force him to logout (destroying the session).

However, the real question is: is it worth it? I haven't seen any similar authentication system yet.

Alessandro Desantis
  • 14,098
  • 1
  • 26
  • 32
  • Hey something i dont understand is. Are databases capable to do counting or see the users last_activity without user interaction ? Or to say if a user doesnt do anything on the database. Does the database counts the time on its own and if it sees that the user has'nt been active for half our to update the table and set the status to offline ? Can this happen without user interaction. If so i can use databases to see the last_activity and update the table without the user interaction – aygeta Nov 06 '11 at 09:58
  • No, a database itself can't detect user's activity. You must update the field in the users table on each request to a page in your site. It'd be easier if you had a front controller. Do you? – Alessandro Desantis Nov 06 '11 at 10:00
  • I have shared hosting. I cant neither install a controller that will do the job in the background. How they do this ? how bulletin board forums do this ? How other sites do this ? There must be some thing to do this. What if a user just turns off the pc . What then ? how can i update the table. :( – aygeta Nov 06 '11 at 10:02
  • "Front controller" means that user's access just one page of your site, and that PHP script will take care of returning the appropriate response. For example, ```/index.php?page=foo``` instead of ```/foo.php```. In this way, you can place the code to update the user's activity only in the ```index.php``` file, and not in the ```foo.php``` file as well. – Alessandro Desantis Nov 06 '11 at 10:04
  • No i dont do this. I use classes and more ajax to do most of the things. But hey please read this -> What if a user just shuts down the pc ? There is no interaction nothing simply nothing. How will i update my table ? – aygeta Nov 06 '11 at 10:08
  • When the next visitor accesses the site, your PHP script will automatically destroy the session if there wasn't any activity for 15 minutes. – Alessandro Desantis Nov 06 '11 at 10:14
  • How can i destroy other users session ? with this new user ? I really dont undersant. How can update the status of this user from other user ? – aygeta Nov 06 '11 at 10:18
  • By "destroy the session" I mean setting the **offline** status in the database. – Alessandro Desantis Nov 06 '11 at 10:20
  • Ok now i understand. When new user comes to my site. I must program a script that will check all last_activity attribute on my table and see if the last_activity was before 30 mins then update that the status attribute to offline. Then every user goes in my site this script will also run to get the last_activity. With this i can update any user's row by other users. I got it now i will try this – aygeta Nov 06 '11 at 10:24
0

I would use a combination of timing out sessions that have not had recent activity and expiring old sessions when a successful log in attempt is made.

As Konerak mentioned HTTP is stateless and there is no built-in way of telling if someone has left your site. You could figure it out with some sort of JavaScript based polling technique, but this would cause a lot of overhead that just isn't necessary in most situations.

Instead you should keep track of the last time there was any activity from a user and store that time in your database or better yet something like memcache. If a users last activity time is longer than a timeout period you decide on assume they are no longer on the site.

The second part would be instead of denying a log in when someone tries to log in after leaving the site without logging out, let them log in and invalidate any old sessions associated with their account.

Useless Code
  • 12,123
  • 5
  • 35
  • 40
-1

As per your scenario, you can use the below logic to check the status of the user:

Instead of checking whether the user is online or offline only depednding upon the value of the table column, use the session variable as well. for example consider below code:

 <?php

  $stauts_from_table_column;

  if($stauts_from_table_column==1 && isset($_SESSION['userid']))
  {
   $user_logged_in = true;
  }
  else
  {
   $user_logged_in = false;
  }     

?>

You can enhance it further, but you get my point i hope.

Ghost-Man
  • 2,179
  • 1
  • 21
  • 25
  • People please read my question. How will i update the table without user interaction. What if a user just shuts down the computer ??? There is no interaction to update the table nothing nothing. What now ? – aygeta Nov 06 '11 at 10:13
  • @aygeta For automatic update in the database, you can run [CRON job](http://www.sitepoint.com/introducing-cron/) in the server which will run every minute and depending upon last activity time of a user will update the column field. Another way without the cron job is, next time a user tries to login, you check if the SESSION is not set and it is set in the database. After authentication update it accordingly. – Ghost-Man Nov 06 '11 at 10:18