I came across a similar thought, and have always had problems with PHP sessions (probably due to stupidity though). I found a class to handle mysql sessions on the net and following the basic principles used there I created my own which uses PEAR DB database access (as I use this in my site).
Maybe you will find it usefull, maybe not.
First the SQL:
CREATE TABLE `sessions` (
`id_session` varchar(32) NOT NULL default '',
`moment` bigint(20) NOT NULL default '0',
`name` varchar(255) NOT NULL default '',
`data` text NOT NULL) TYPE=MyISAM;
Now the class
<?php
// remove 'extends config class' if not using this as a child of a global class. As you see the $db handler is always passed by reference.
class session extends config_class {
var $session_limit = 300; //I have this in my config class, it is the session timeout in seconds, this should work fine for you here
//constructor function, db by reference
function session (&$db) {
session_start();
$id_session=$this->id();
//now delete any old sessions
$deletesql = "DELETE FROM sessions WHERE moment<(UNIX_TIMESTAMP()-$this->session_limit)";
$deleteresult = $db->query($deletesql);
//now see if there is already an open session
$momentsql = "SELECT moment FROM sessions WHERE (id_session='$id_session') ORDER BY moment DESC";
$momentrow = $db->getRow($momentsql);
//see if there was a result
if (!$momentrow) {
//make a new session
$insertsql = "INSERT INTO sessions VALUES('$id_session', UNIX_TIMESTAMP(), '', '')";
$insertresult = $db->query($insertsql);
}
else {
//keep current session alive
$updatesql = "UPDATE sessions SET moment=UNIX_TIMESTAMP() WHERE (moment='$momentrow[moment]')AND(id_session='$id_session')";
$updateresult = $db->query($updatesql);
}
}
//register a session variable e.g to save $id name will be 'id' dan data is 'abc123etc'
function register($name, $data, &$db) {
$id_session=$this->id();
$data = serialize($data);
$checkquery = "SELECT id_session, name FROM sessions WHERE (id_session='$id_session')AND(name='')";
$checkresult = $db->query($checkquery);
$numresults = $checkresult->numRows();
//now if there is a result (empty session starter) we may as well just use that row
if (count($numresults)==1) {
$updatequery = "UPDATE sessions SET name='$name', data='$data' WHERE id_session='$id_session'";
$updateresult = $db->query($updatequery);
}
else {
//check if the variable is already registered if registered then update it
if ($this->is_registered($name, $db)) {
$updatequery = "UPDATE sessions SET data='$data' WHERE (id_session='$id_session') AND(name='$name')";
$updateresult = $db->query($updatequery);
}
else {
//create new
$insertquery = "INSERT INTO sessions VALUES($id_session, UNIX_TIMESTAMP(), '$name', '$data'";
$insertresult = $db->query($insertquery);
}
}
$checkresult->free();
}
//unregister variable, no return
function unregister($name, &$db) {
$id_session=$this->id();
//check if this is the last variable registered, we don't want to end the session here
$checkquery = "SELECT count(id_session) FROM sessions WHERE (id_session='$id_session')";
$checkresult = $db->getOne($checkquery);
if ($checkresult==1){
//so we need to update then
$updatequery = "UPDATE sessions SET name='', data='', moment=UNIX_TIMESTAMP() WHERE (id_session='$id_session') AND (name='$name')";
$updateresult = $db->query($updatequery);
}
else {
//get rid of it, we have more left
$deletequery = "DELETE FROM session WHERE (id_session='$id_session')AND(name='$name')";
$deleteresult = $db->query($deletequery);
}
}
// check if a variable is registered
function is_registered($name, &$db) {
$id_session=$this->id();
//check if it is registered, if so return 1, if not return null
$checkquery = "SELECT id_session, name FROM sessions WHERE (id_session='$id_session')AND(name='$name')";
$checkresult = $db->query($checkquery);
$numresults = $checkresult->numRows();
$checkresult->free();
if ($numresults==1) return 1;
else return;
}
//Return a value
function get($name, &$db) {
$id_session=$this->id();
$selectquery = "SELECT data FROM sessions WHERE ((id_session='$id_session')AND(name='$name'))";
$data = $db->getOne($selectquery);
return unserialize($data);
}
//Get the session_id from php
function id() {
return(@session_id());
}
//end the session, no return
function finish(&$db) {
$id_session = $this->id();
$endquery = "DELETE FROM session WHERE id_session='$id_session'";
$end = $db->query($endquery);
@session_unset();
@session_destroy();
}
//Return number of active sessions at this time, lifetime decides how long until a user is not seen as online
// this cant be longer than the session timeout, default is 5 mins
function nb_users(&$db, $lifetime=300) {
$usersquery = "SELECT id_session FROM sessions WHERE moment>(UNIX_TIMESTAMP()-$this->session_limit) GROUP BY id_session";
$usersresult = $db->query($usersquery);
$numusers = $usersresult->numRows();
$usersresult->free();
return $numusers;
}
}
?>