Page 1 of 2
[SOLVED]Sessions Help
Posted: Wed Apr 07, 2004 10:55 am
by Pyrite
I have a website where I have implemented a sessions db table kind of like phpBB has. When sombody logs in, a record is created in the sessions table, and when they logout, that record is deleted. My problem is that if they close the browser window, the session of course expires, but the record still remains in the sessions table. This is for a Who's Online script by the way. Is there a solution? Or a better way to implement a "Who's Online" method that will fix this?
Re: Sessions Help
Posted: Wed Apr 07, 2004 10:57 am
by Roja
Pyrite wrote:I have a website where I have implemented a sessions db table kind of like phpBB has. When sombody logs in, a record is created in the sessions table, and when they logout, that record is deleted. My problem is that if they close the browser window, the session of course expires, but the record still remains in the sessions table. This is for a Who's Online script by the way. Is there a solution? Or a better way to implement a "Who's Online" method that will fix this?
Anytime someone logs in, do a "delete all where date > XXXX" where XXXX is the period of time for an expired session.
Simple, effective, accurate.
Posted: Wed Apr 07, 2004 10:58 am
by patrikG
You'll have to write your own session handler - it's quite well documented in the manual:
[php_man]session_set_save_handler[/php_man]
Basically, when the session times out or is destroyed you bespoke session handler is invoked - and from that you can delete the record.
Edit: moved to php - code
Posted: Wed Apr 07, 2004 11:22 am
by Pyrite
Roja:
yes but in the meantime they show up as Online. Say somebody logs in one day, and closes the browser window. Sure their session is expired, but they show up to others as Online until they login again say a week later.
patrikG:
Not quite sure I follow you, can you explain a bit more. My problem isn't really to do with sessions but more to do with deleting a record from a database when somebody closes their browser window without logging out.
Posted: Wed Apr 07, 2004 11:24 am
by JayBird
are you trying to re-invent the wheel for any reason? there ore plenty of ready made userOnline scripts out there that use databases.
Mark
Posted: Wed Apr 07, 2004 12:12 pm
by Pyrite
Heh, If you read through 99% of my posts on devnetwork, it would seem that I am trying to re-invent the wheel yes. My online script works fine, it's just this little possible scenario that I don't have a solution for. I'll look for some other code, but I want to understand the solution, not just trust someone elses. Thanks.
Posted: Wed Apr 07, 2004 12:40 pm
by Roja
Pyrite wrote:Roja:
yes but in the meantime they show up as Online. Say somebody logs in one day, and closes the browser window. Sure their session is expired, but they show up to others as Online until they login again say a week later.
I didnt define how long the sessions last.
If you set it for say, 15 minutes, then if they havent done anything in 15 minutes, then they are logged off.
Your scenario, with a 15 minute expire:
"BOB" logs in today 8am, and close the browser window. Their session is marked at 8am. At 8:16, someone else logs in, the delete query runs, and sees Bob's session, with a time stamp > 15 minutes ago (8:00). It deletes his record.
Now he isnt in the session table, and isnt counted as online.
Posted: Wed Apr 07, 2004 12:47 pm
by Pyrite
Now see I could do that, but it would require other users to trigger the script. Lets look at this problem by example. phpBB (yes these forums we are using) has the same problem.
Open (well you already are really), but go to
viewonline.php
You see yourself when you are logged in right. Close the browser window (don't logout) and delete your cookies if you told it to always log you in. Then go back to
viewonline.php
You will see your name there still listed as online even though you closed the browser window thus ending your session. I haven't seen any solutions to this other than trigger either by crontab/scheduled taks or as Roja suggested other users calling a script to delete records based on time values. Is that the only way, surely not?
My last idea would be to forget the database for this and just read the session files from the server and parse them for the usernames to show who is online, cause when the session ends via logout or browser close, the file gets deleted on the server, can this be done??

Posted: Wed Apr 07, 2004 1:14 pm
by Roja
Pyrite wrote:I haven't seen any solutions to this other than trigger either by crontab/scheduled taks or as Roja suggested other users calling a script to delete records based on time values. Is that the only way, surely not?
Problem: You are creating a record, and you need it to be gone when the user is.
Solutions:
- Delete records based on time
- Delete records based on logout
Now, the second is what you have another problem with - people logging out without CLICKING logout.
A way to deal with THAT problem would be to set an onclose() event (javascript) that would open a page that deletes their session.
But its far more effective to simply delete old sessions. Lets say you set it at 30 minutes.. most people will actively do SOMETHING in 30 minutes. So at worst, the info is inaccurate for 29 minutes.
Posted: Wed Apr 07, 2004 2:48 pm
by patrikG
What I mean with creating your own session handler: a session gets destroyed after the session times out. If you define a bespoke handling function for that, you can simply add a "delete record" there.
That way, you it all happens without worrying about it once set up correctly.
Posted: Mon Apr 12, 2004 12:32 pm
by Pyrite
patrikG: Can you help me with this bespoke handling function? I can't find any info about this on the net related to php. Is there some link you can point me to, or some php code to do this?
I have temporaly solved this problem by putting this query in my logout script to delete possible old sessions in the db that have been around for 24 hours or more since the session began.
Code: Select all
DELETE FROM tbl_sessions WHERE (sess_time+'86400' < NOW()) AND (sess_uid='$ID')
Posted: Mon Apr 12, 2004 12:35 pm
by patrikG
Sorry, I should have mentioned the appropriate PHP function: [php_man]session_set_save_handler[/php_man]. The example code in there is quite straightforward, actually
Edit: oh, I noticed I actually did post that one before. Excellent, one more reason to go and drink a glass of red tonight

Posted: Mon Apr 12, 2004 1:28 pm
by Pyrite
So, I should run session_set_save_handler when a user logs in to tell php what to do when the session ends? I just don't understand what this is used for... n00B!
Posted: Mon Apr 12, 2004 2:09 pm
by patrikG
session_set_save_handler allows you to use your own, custom-built functions instead of the default PHP ones. It does look a bit weird at first - but it's actually quite straighforward:
When a new session starts, PHP runs your custom-built function instead of the default one. Example (taken from the code in the php manual example code below):
Code: Select all
function destroy($id)
{
global $sess_save_path, $sess_session_name;
$sess_file = "$sess_save_path/sess_$id";
echo "DUDE, you destroyed me. AAAAAAAAAAAAAAARGH!";
return(@unlink($sess_file));
}
Now every time a session is destroyed, the person doing it will feel bad
php manual example wrote:Code: Select all
function open($save_path, $session_name)
{
global $sess_save_path, $sess_session_name;
$sess_save_path = $save_path;
$sess_session_name = $session_name;
return(true);
}
function close()
{
return(true);
}
function read($id)
{
global $sess_save_path, $sess_session_name;
$sess_file = "$sess_save_path/sess_$id";
if ($fp = @fopen($sess_file, "r")) {
$sess_data = fread($fp, filesize($sess_file));
return($sess_data);
} else {
return(""); // Must return "" here.
}
}
function write($id, $sess_data)
{
global $sess_save_path, $sess_session_name;
$sess_file = "$sess_save_path/sess_$id";
if ($fp = @fopen($sess_file, "w")) {
return(fwrite($fp, $sess_data));
} else {
return(false);
}
}
function destroy($id)
{
global $sess_save_path, $sess_session_name;
$sess_file = "$sess_save_path/sess_$id";
return(@unlink($sess_file));
}
/*********************************************
* WARNING - You will need to implement some *
* sort of garbage collection routine here. *
*********************************************/
function gc($maxlifetime)
{
return true;
}
session_set_save_handler("open", "close", "read", "write", "destroy", "gc");
session_start();
// proceed to use sessions normally
Posted: Mon Apr 12, 2004 4:07 pm
by Pyrite
Ok, say I have my own destroy session function. It will only be called though when a user calls the script calling my custom destroy function right? So how does that solve the problem if the user doesn't call my script, and just closes the browser? Cause when he just closes the browser, no code is called to destroy the session, instead, PHP by its nature ends the session. That right?