Page 1 of 1

[SOLVED] Session Handler Class Problems

Posted: Tue Nov 28, 2006 7:07 am
by HCBen

I found the problem: I was selecting the data in the read function as an array instead of a single result record. :oops:

I've since updated the code below.


My custom session handler class isn't working right and I can't figure out what the problem is. I've done all the trouble-shooting tasks that I can think of and I still don't know why it won't work.

Here is the class:

Code: Select all

class session
{
	private $db_obj;
	private $timeout;
	
	public function __construct() 
	{
		
		$this -> timeout = ini_get('session.gc_maxlifetime'); // 24 minutes;
		
		session_set_save_handler
		(
			array(& $this, 'open'),
			array(& $this, 'close'),
			array(& $this, 'read'),
			array(& $this, 'write'),
			array(& $this, 'destroy'),
			array(& $this, 'gc')
		);
		
		// Don't need this anymore b/c of the __destruct function below. But I want to keep it for reference.
		//register_shutdown_function('session_write_close');
		
		if (empty($_SESSION)) session_start();
	}
		
	public function open() 
	{
		$this -> db_obj = new dbo;
		$this -> db_obj -> setDBName('SESSIONS');
		return true;
	}
	
	public function close() 
	{
		$this -> gc($this -> timeout);
		$this -> db_obj -> closeDBConn();
		return true;
	}
	
	public function read($session_id) 
	{
		$sql_get_session_data = ' SELECT Session_Data FROM Session WHERE Session_ID = '._escapeSQL($session_id).' ';
		if ($session_data = $this -> db_obj -> getData($sql_get_session_data,'record','Session_Data')) return $session_data;
		else return ''; 
	}
	
	public function write($session_id, $session_data) 
	{
		$date_time = _dateTime('now');
		
		$sql_check_session_id = ' SELECT Session_ID FROM Session WHERE Session_ID = '._escapeSQL($session_id).' ';
		if ($this -> db_obj -> getData($sql_check_session_id,'record','Session_ID'))
		{
			$sql_update_session = ' 
				UPDATE Session SET 
				Session_Updated = '._escapeSQL($date_time).',
				Session_Data = '._escapeSQL($session_data).'
				WHERE Session_ID = '._escapeSQL($session_id).' ';
			if ($this -> db_obj -> setData($sql_update_session)) return true;
			else return false;
		}
		else
		{
			$sql_insert_session = ' 
				INSERT INTO Session (Session_ID, Session_Date, Session_Updated, Session_Data) 
				VALUES (
					'._escapeSQL($session_id).',
					'._escapeSQL($date_time).',
					'._escapeSQL($date_time).',
					'._escapeSQL($session_data).') ';
			if ($this -> db_obj -> setData($sql_insert_session)) return true;
			else return false;
		}		
	}

	public function destroy($session_id) 
	{
		$sql_delete_session = ' DELETE FROM Session WHERE Session_ID = '._escapeSQL($session_id).' ';
		if ($this -> db_obj -> setData($sql_delete_session)) return true;
		else return false;
	}
	
	public function gc($max) 
	{
		// $max = default session.gc_maxlifetime of 24 minutes
		// Delete any sessions in the database that are older then 24 minutes:
		$session_exp_date = _dateTime((int) (time() - $max));
		$sql_delete_session = ' DELETE FROM Session WHERE Session_Updated < '._escapeSQL($session_exp_date).' ';
		if ($this -> db_obj -> setData($sql_delete_session)) return true;
		else return false;
	} 
	
	public function __destruct()
	{
		session_write_close();
	}
}
And here's how I'm calling it on a test page:

Code: Select all

// I use an auto_prepend file that includes the __autoload function.

new session();

//session_start();

echo $_SESSION['time'].'<br>';  // First time this errors, as expected.

$_SESSION['time'] = time(strtotime('now'));
echo $_SESSION['time'];
Now, if I use the default session handling method, everything works as it should. The page first loads with a notice message about the first "Undefined index: time in ...", but if I refresh the page, the first time session variable displays correctly - showing the time that was previously set.

However, if I run the code as I have it shown above using the session object, I continue to get the notice message about the undefined index for time, yet when I check the database there is a string in the session data column for the time and even when I echo the $session_data variable in the read() function in the class above, I get the session time that was previously set. It just won't pass through to the page.

It's as if the session is restarted every time I reload the page yet I don't understand why or how.

I've tried all of the following as well, with no success:

- Removed the session_set_save_handler and session_start() functions from the class and added them to the page immediately after setting the session object.
- Prefaced session_start() with "if (empty($_SESSION))"
- Used register_shutdown_function('session_write_close) in the constructor as apposed to the session_write_close() in the destructor.

Does anyone have any suggestions or notice anything wrong?

Thanks in advance,

Ben

Some additional information that my be useful:
PHP Version: 5.2.0 (ISAPI)
Database: MSSQL
Server: Microsoft IIS6
DB Function: ODBC