I'm currently trying to display all online users on my SITE'S userpage using the php session variables. To do this, whenever a user logs in or out, a column in a database gets set to "1" or "0".. However this doesn't entirely work since the database doesn't get updated when the user closes their browser (and therefor destroys the session). So is there another way of checking if a certain sessionid is set??
I also want to know how the twitter and facebook handle this ?
You almost have it. The way that the vast majority of sites deal with the issue is to have a table like you do, but they add a timestamp to it and update the timestamp when a new page is loaded.
When querying the table, you simply look for say the last five minutes of active users and they are the "live" users on the site.
Technically, you don't even need to keep the "logged in/out" value in that table. If they have been logged in within the lat five minutes, they are probably still about.
There is no guaranteed, sure-fire, totally bullet-proof way of checking if a user is there or not. You can do some tricky JS to ping on and off, you can add even more JS that will try to alert the db when the user navigates away from the page - but at the end of the day, you cannot do anything if a browser is closed unexpectedly, or if that user loses power, or network.
On top of that web browsing is by default stateless and doesn't maintain a connection to the user after the server has finished sending code. The best we can efficiently do is update a table when the user does something new and assume they will be around for a few minutes at least.
I haven't checked but Twitter and Facebook most likely have Javascript code which notifies the server when somebody closes the page, probably coupled with a periodic heartbeat and timeout.
Check the onunload event and XMLHTTPRequest to see how you can make a request to your PHP application notifying of an user leaving (a library like jQuery might help you do this much more easily).
Add a field "last_visit" to user's Table and update it every time when user visit your site
When user login to your site find "last_visit" time and current time,after that use this function
$time_period = floor(round(abs($current_time - $last_visit)/60,2));
if ($time_period <= 10)
$online_offline_status = 1;
else
$online_offline_status = 0;
}
and then print your final result
<?php if (
$online_offline_status == 0){ ?>
<span style="color:#FF0000;">Offline</span>
<?php } else if ($online_offline_status == 1) {?>
<span style="color:#669900;">Online</span>
<?php }?>
Related
I have a table on my database called 'Log'. This Log table contains ID, Username, LoginTime and LogoutTime. That's all.
It's really easy to INSERT into ID, Username and LoginTime columns...
But dealing with LogoutTime, I was thinking there will be 2 condition :
User click logout button >> PROBLEM SOLVED, I can easily put INSERT script on my logout.php to handle LogoutTime column.
User just run away from my website by clicking close button of their browser >> THIS WILL CAUSE A PROBLEM. How can I write to LogoutTime column in this situation like this?
can it be handle by PHP only? I mean, doesn't have to use jQuery... Thanks before.
The most common solution to get this done is by using a timeout. So you run periodically a cron which checks whether there are users which are not active anymore. For example it can be no requests done for the last half hour. Then add the logout time at that moment.
So every action update the user session with the last request time so you know when they have a timeout.
Controlling 100% a closing browser is not possible. Think for example about a power failure at the client computer, you will get nothing back for sure.
You can implement something similar to this, the time can be different according to your need
if (isset($_SESSION['browser_last_activity']) && (time() - $_SESSION['browser_last_activity'] > 1800)) {
// request 30 minates ago
// set the logout time here
}
$_SESSION['browser_last_activity'] = time(); // update last activity time
But there is no way you can implement functionality 100% meet your requirements with php.
And with javascript you can try with onbeforeunload, it is good practice than do it with javascript and not in php because of overhead reasons.
In IE you can try something like this:
< body onbeforeunload="alert('Closed!');">
I've binged a lot for this stuff, but couldn't find direct ANSWER,
I've searched for this here,
But
I am still beating my head against the wall trying to implement,
How do I do update query after session expired?
I'm not talking about explicit clicking "Logout" button
Here's basic SQL structure:
CREATE TABLE auth_users (
email varchar(40) NOT NULL,
password varchar(40) NOT NULL,
online ENUM('1') DEFAULT NULL <-- HERE, it updates to 1 when user logged in, it updates back to NULL when user explicitly clicks on LOGOUT
) type=MyISAM;
Class Hierarchy:
interface {
function login();
function logout();
//calls after succes authorization
function set_as_online();
//calls from within logout() method
function set_as_offline();
}
BUT IT DOES NOT UPDATES BACK TO NULL WHEN USER CLOSES HIS BROWSER,
For example,
Assume we have two users: User-A, User-B
User A logged successfully, now User-B can see User-A as ONLINE user.
If User-A forget to click "LOGOUT" and would close his browser,
user-B still can see User-A as ONLINE. That's the problem.
For example,
Facebook handles this very well,
Assume your friend just closed the browser (i.e his session does not exists anymore),
then somehow you can see him as OFFLINE
What am I doing wrong? Incorrect approach of handling offline/online users?
Another approach is needed here i think. Don't set a online/offline flag, but a 'last_seen' timestamp. Ie. with every request update the record to the current timestamp. If you want to know if the user is online, just do:
if($current_time - $last_seen_time < $session_expire_limit) {
// online
} else {
// offline
}
Otherwise you'd need a cronjob of some sort to automatically reset the online flag in your database after a certain time, but then still you'd need a last_seen column.
// edit
i don't know exactly how facebook does it, but it could be one of the following; for the chat and notify functionality facebook opens up a 'stream', which is in fact a little ajax call which is kept alive by the server (btw, this ajax call is refreshed every 40 seconds). Possibly this stream is used to track online users. Another option, but less likely, is that an event is attached to the window.unload event. This is less likely because a page refresh, a clicked link to another facebook page etc. is also triggering the event. This would mean that every time an internal facebook link is clicked the event should be unbinded from the browser.
Can't think of another way atm, just some suggestions. Unfortunately those are quite labor-heavy to implement, I assume my suggestion above (before the edit) should be suitable for a common website.
I am not sure how facebook controls this stuff but i can suggest you from the top of my head how i would approach this matter.
I would add a new field on your auth_users table of type Date that will represent the session_expiry_time .
Then inside your html pages you should implement some silent ajax code that will call a dummy php page on the server (the interval is something very important because you have to balance performance and functionality). This dummy page will update the session_expiry_time of the user in
the auth_users table.
Therefore, in any given time, checking a user's session_expiry_time against current time will determine if the user is online or not.
http://de2.php.net/manual/en/features.connection-handling.php
you can with register_shutdown_function() und connection_aborted() your intend achieve
Use a simple JavaScript on the page
In the body tag
The callLogoff() should be replaced with the JavaScript function that calls log off.
Try it.
I'm not awesome enough to write a chat application, and I'm trying to get one to work, and I've recently downloaded one from here, it's pretty good so far, as I've tested it out on XAMPP, but I have a slight problem. I'm trying to generate a list of online users to give it a more practical application-like feel, but the problem with that, is I have no clue how to do it easily.
When users login to my site, a session named g_username is created, (the chat says 'username', but I'll fix that) and from what I see so far, the easiest method would be to store their username in a database called OnlineUsers and call that data via Ajax, but, the other problem, is that it's session based, and sometimes the users can just leave, without logging out, and I intended to run a script to logout the user from both the OnlineUsers table, and by deleting the session.
If they leave without logging out, they'd be online forever! I could potentially suffix a bit of code on every page, that toggled an ajax event on page close, the event being a script that kills their OnlineUsers table record, but then again, that would load the server with useless queries as users jump between pages, as far as I'm aware.
Creating my entire site in Ajax isn't really an option, as it's a load of different sites combined in to 1 'place' with a social 'layer' (if you will) from a social service.
Does anyone see a way to do this that would make sense, and be easy to integrate, and do with Apache, without command line access?
You could so something like storing a timestamp of the users last action in a database, comparing that timestamp when outputting online users and making sure that it was done at most 1 min ago.
Run on all/vital pages:
(Deciding if the last action is outdated, you could also check if it was done for one minute ago to reduce the database-load)
if($user['lastAction'] < time()) {
//update into database, last action is outdated
}
When calculating the amount of users online and is within the loop of each timestamp
//If the users last action was within a minute, the user is most likely online
if(($row['lastAction']- time()) > 60*60)
//count user as online
you could have a cron job [if you have cpanel] running on the server once every 60secs or so, that checks when a user last sent anything via the chat if they have not in the last lets say 5mins then remove their entry from the online users list.
I've created a very simple multiuser game for learning purposes.
As users log on, each other user gets an update of all currently logged in users.
When a user logs in, it simply sets a value for that user in the SQL database to 1. When they're logged out, the value should be 0.
I'm using $(window).unload(function() {}); to try to catch tab/browser closes, but it only sortof works.
Two questions:
Is there a better way to catch browser or tab close?
In the event that it misses the tab close, or their machine crashes, or internet connection dies, or the user simply walks away from the machine, I want to go ahead and log them out automatically.
I'm using an HTML/Jquery frontend with PHP backend. What can I do to accomplish the second question? I assume I need to do it in PHP.. we're working under the assumption that the browser is likely no longer even around, hence not processing jquery stuff. Can PHP do something on an continuous timer that checks to see if the user is still around... without simply having the users click a button every 10 seconds?
Edit:
There's a potential solution here: How to detect if a user has logged out, in php?
But I'm using ajax to avoid page refreshes. Ideally, the user will never f5 the page, or click any buttons (I'm testing, remember, this is not a for real app). Will PHP see last activity without a full page refresh?
Edit2:
I've added the following code to my PHP, with a corresponding jquery function using setInterval
if (isset ($_POST['keepalive'])) {
if (filter_input(INPUT_POST,'keepalive') == '1') {
$name = $_SESSION['name'];
$time = time();
mysql_query("UPDATE tictac_names SET keep_alive = '$time' WHERE name ='$name'") or die(mysql_error());
}
}
This plugs a unix epoc timestamp into my table, which will be super easy for simple calculations.
My question now is: How do I tell PHP to run a check for each logged in user ever X number of seconds? My PHP backend file is primarily just set to catch post variables and run code, then hand it back to jquery. Since this code is intended to log out inactive browsers/users, I can't rely on jquery sending a request to PHP, and there's no refresh of the PHP. Do I need to do some kind of cron job or some bizarreness to get PHP to check for all users who have not updated in the last X seconds?
Help!
Don't know about the first question, but how about a suggestion on the second:
When the user is 'active', will they be causing page requests fairly regularly? If so, you could have a system whereby a logged-on user is periodically logged in your SQL database, with a timestamp. Then have another script look up all those users whose timestamps are older than a specified period (whatever you like, eg 10 seconds) and have them set to '0'.
I could suggest some code but maybe this isn't what you're looking for - let me know.
EDIT: OK, the link from your edit seems to have been answered with a similar system to what I just suggested. If you use AJAX you can call a php script periodically in the background to set and check timestamps from the SQL table.
You could implement a $_SESSION based solution, like Gumbo answered this question. Then you could adapt it to handle your database requirements.
if you used html5 socket connections as your way of connecting to the server, your socket server script would know when a subscriber disconnects. this would also allow you to push data to all the clients in real time without long polling. the only problem is I don't know what the support of html5 sockets is at the moment. I have done something similar using Flash, which also supports socket connections.
Instead of just setting a flag when a user logs in, log a timestamp you can use to determine the time of log-in. Also, you can have your client, call-home using AJAX some PHP script to save in the database the timestamp of last user-activity.
You can then execute a session cleaner script periodically using a cron job in the server. The script would query the database to detect the stale sessions and do the log-off (set the logged on flag to 0). If the server has PHP CLI (Command Line Interface) installed, you can code the script in PHP.
A possible way to only catch a user who comes back to the site after they closed the window could be using a database for user ID, IP and time like so:
$_SESSION['ip'] = $_SERVER['HTTP_CLIENT_IP'];
if(isset($_SESSION['ip'])){
if(Logedin){ // This login detection can be set by cookies can very depending on situation
mysql_query("INSERT INTO users SET user_login=\"".'1'."\",user_id=\"".$idfromlogin."\",user_ip=\"".$_SESSION['ip']."\",user_time=\"".time();."\"");
}
Then we can check this every time a page loads against the time(); if the user closes window by "X" button the session is over. Now we have to start a new session but that's why we saved the time in the database.
$_SESSION['ip'] = $_SERVER['HTTP_CLIENT_IP'];
if(isset($_SESSION['ip'])){
if (!$sql = mysql_query("SELECT * FROM users WHERE user_ip=".$_SESSION['ip'])){
die('Error: ' . mysql_error());
}
$row = mysql_fetch_array($sql);
if ($row['user_time'] + 10 * 60 < time()){ // this is 10 minutes have passed
// now to find the user database by the session database the logins is your method of loging in a user from logins database with pass and name
if (!$user = mysql_query("UPDATE logins SET user_isloggedin=\"".'0'."\" WHERE user_id=".$row['user_id'])){ //from the users database
die('Error: ' . mysql_error());
}
}
This only shows a way to check IP if they came back and the recorded time has passed previous. This does not show how to catch when some one presses "X" button. IP's can change so I would write a check IP function:
function getRealIpAddr(){
if (!empty($_SERVER['HTTP_CLIENT_IP'])){ //check IP from share internet
$ip=$_SERVER['HTTP_CLIENT_IP'];
} elseif (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])){ //to check IP is pass from proxy
$ip=$_SERVER['HTTP_X_FORWARDED_FOR'];
}else{
$ip=$_SERVER['REMOTE_ADDR'];
}
return $ip;
}
I assume that, users are shown as online and offline on logout. Destroying session or cookie will require client browser in working mode.
Solution
I also assume there is a timestamp column maintained. Set an interval to check time-gap between current TS and Last Timestamp. Also update your own TS against your id to current TS.
setInterval(function(){
$.ajax({
url: "/backend.php?userid=id",
success: function(resoponse){
console.log(response);
}
});
}, 10000);
backend.php
$user_id = $_GET["userid"];
$query = "select * from table name where (GETDATE() - timestamp) > 60";
$resut = mysqli_query($con, $query);
while($row = mysqli_fetch_assoc($result)){
//set there status = 0 as offline
$other_user_id = $row['user_id'];
mysqli_query($con, "update tablename set status = 0 where user_id = '$other_user_id'");
}
//update your own timestamp
mysqli_query($con, "update tablename set timestamp = GETDATE() where user_id='$user_id'");
This would check user activity, or basically check if that js is running or not. If browser was closed then TS for that user won't get updated hence GETDATE() - timestamp will be greater than 60. Now other users who would be running the web app would also run the same script, checking and updating all users status as per condition.
When user closes his tab he would still be online for at least 1 minute.
I had a similar problem and found solution here PHP auto logout on tab close.
Environment : PHP/MySQL/Jquery
I would like to refresh the page (ex: index.php) when new data stores in to the table (ex : new_entry_table) checking for every one minute. The same page will be opened in many machines(pc-browsers) at a time all should get refresh when new data arises.
using jquery and database check i tried the following:
setInterval(function(){
$.post("new_data_check.php", function(data) {
if(data > 0){
$("#container").fadeOut('fast').load(location.reload());
}
});
return false;
},60000);
new_data_check.php: : checks
for new data in the test_db where
newdata_field=0 ; : If any new
data arises echo "1"; And update the
newdata_field=1; to stop constantly
refreshing the page. : else echo
"0"; : Just for a trigger
So the above jquery code checks new_data_check.php every 1 min for the trigger , if any trigger arises it will refresh the container.But its getting refresh only one opened session other opened sessions(in other browser or other pc) not getting refreshed.
Suggest a better way to do this. Thanks.
Your new_data_check.php file will need to keep track of all the users that are independently viewing the page.
If not, this will happen:
User 1 and User 2 are both logged into the site.
User 1 does the check 5 seconds before User 1, there is new data.
User 1 completes his request. The server clears the new_data bit.
User 2's request arrives 5 second later. Hedoes his request, but at this point, User 1 has set the new_data field to 0. His data is stale, but User 1 has effectively co-opted him.
By the looks of it, you're not supplying it with any information that would identify the user - unless the server is determining that using the IP address. If that's the case, remember that it's likely everyone behind a small network is going to have the same external ip address. So it can't tell people at an office apart.
What you could do is generate some kind of unique hash for each session and pass that off to the browser. The javascript can then provide the php script that same token.
Another solution without any sort of special bit, would be to pass along a timestamp with the request. Essentially, the client says "my latest bit of data arrived at 9:21:53 PM" The server then checks and responds "My most recent data was created before that, so you're still good. " or "I've got something that was created or modified on 9:22:53PM, you should download it."
With that method, you don't need to worry about who's who. Instead, you need to have modification/creation times on the data you're checking for staleness. You also need to make sure that the clients clock is synchronized correctly - better yet, don't trust the clients date and time information. Maybe utilize your new_data_check.php to provide the script with a timestamp it can pass along on subsequent requests.