[SOLVED]Sessions Help

PHP programming forum. Ask questions or help people concerning PHP code. Don't understand a function? Need help implementing a class? Don't understand a class? Here is where to ask. Remember to do your homework!

Moderator: General Moderators

User avatar
Pyrite
Forum Regular
Posts: 769
Joined: Tue Sep 23, 2003 11:07 pm
Location: The Republic of Texas
Contact:

[SOLVED]Sessions Help

Post 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?
Roja
Tutorials Group
Posts: 2692
Joined: Sun Jan 04, 2004 10:30 pm

Re: Sessions Help

Post 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.
User avatar
patrikG
DevNet Master
Posts: 4235
Joined: Thu Aug 15, 2002 5:53 am
Location: Sussex, UK

Post 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
User avatar
Pyrite
Forum Regular
Posts: 769
Joined: Tue Sep 23, 2003 11:07 pm
Location: The Republic of Texas
Contact:

Post 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.
User avatar
JayBird
Admin
Posts: 4524
Joined: Wed Aug 13, 2003 7:02 am
Location: York, UK
Contact:

Post 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
User avatar
Pyrite
Forum Regular
Posts: 769
Joined: Tue Sep 23, 2003 11:07 pm
Location: The Republic of Texas
Contact:

Post 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.
Roja
Tutorials Group
Posts: 2692
Joined: Sun Jan 04, 2004 10:30 pm

Post 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.
User avatar
Pyrite
Forum Regular
Posts: 769
Joined: Tue Sep 23, 2003 11:07 pm
Location: The Republic of Texas
Contact:

Post 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?? :roll:
Roja
Tutorials Group
Posts: 2692
Joined: Sun Jan 04, 2004 10:30 pm

Post 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.
User avatar
patrikG
DevNet Master
Posts: 4235
Joined: Thu Aug 15, 2002 5:53 am
Location: Sussex, UK

Post 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.
User avatar
Pyrite
Forum Regular
Posts: 769
Joined: Tue Sep 23, 2003 11:07 pm
Location: The Republic of Texas
Contact:

Post 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')
User avatar
patrikG
DevNet Master
Posts: 4235
Joined: Thu Aug 15, 2002 5:53 am
Location: Sussex, UK

Post 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 :)
User avatar
Pyrite
Forum Regular
Posts: 769
Joined: Tue Sep 23, 2003 11:07 pm
Location: The Republic of Texas
Contact:

Post 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!
User avatar
patrikG
DevNet Master
Posts: 4235
Joined: Thu Aug 15, 2002 5:53 am
Location: Sussex, UK

Post 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
User avatar
Pyrite
Forum Regular
Posts: 769
Joined: Tue Sep 23, 2003 11:07 pm
Location: The Republic of Texas
Contact:

Post 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?
Post Reply