Deprecated: preg_replace(): The /e modifier is deprecated, use preg_replace_callback instead in /share/CACHEDEV1_DATA/Web/www/libraries/UBBcode/text_parser.class.php on line 228

Deprecated: preg_replace(): The /e modifier is deprecated, use preg_replace_callback instead in /share/CACHEDEV1_DATA/Web/www/libraries/UBBcode/text_parser.class.php on line 228
Custom session handlers in PHP

Comments Blog About Development Research Sites

Custom session handlers in PHP

Aug 2, 2008
A very usefull thing to do in PHP is to replace the default session handler with your own. This gives you the ability to count active visitors, retrieve statistical data about who logs in from where and more without having to loop trough all the files in your session store path. Furthermore this allows you to use your site in a (load balanced) cluster without people inexplicably logging out whenever they switch webservers.

Unfortunately the documentation on this is somewhat limited to nonexisting, though it is quite easy to figure out.

Activating your custom session handler:
For this we need a class and members that handle the various operations, make sure they are used and register a shutdown function so we still have our database connection when we shut down the session.
Code (php) (nieuw venster):
1
2
3
4
5
6
7
8
9
session_set_save_handler(array(& $this, 'open'),
                         array(&
$this, 'close'),
                         array(&
$this, 'read'),
                         array(&
$this, 'write'),
                         array(&
$this, 'destroy'),
                         array(&
$this, 'gc'));
register_shutdown_function("session_write_close");
session_set_cookie_params(self::COOKIE_TIMEOUT);
session_start();


The first block should be fairly obvious: session_set_save_handler requires references to 6 functions that perform various actions. Each argument is a callback function, which means either a function, a static class member (className::member), an object with a member (as in this case) or one of the more exotic callback options.

Next, we use register_shutdown_function. If we do not do this, the session's close handler will be called after everything else is destroyed, including our open database connection! By registering a shutdown function we force PHP to execute that function first before destroying our resources and objects. Alternatively we could have used a __destruct member, though that would rely upon the order of destruction to be session first and DB handler second, which is more likely to fail.

Lastly we set a cookie parameter (first argument is the session timeout in seconds) and actually start the session - note that this order is important, you should not start the session before registering a custom handler or your handler won't be used!

The Various Session Handling Functions

open ($savePath, $sessionName)
This should most likely open a file handler, with fopen for example. Since we do not require an open file (we use the DB instead) you can leave this function empty except for a 'return true;' since that's what PHP expects.

public function close ()
As with open, this probably closes the file pointer (with fclose for example), should do little more than return true.

read ($id)
Read the session data with ID $id from our database. Sessions are stored in the format [id] => [dataString] where [dataString] is an encoded string which contains all information in the session. Each visitor should have a unique [id] where his data is stored and retrieved from.

To prevent session theft you can also store the IP address of the last request and only return the data when the new request comes from the same address. It's a bit superflous, but can't hurt. This function should always return a [session data] string exactly as it was stored.

write ($id, $data)
The parameters are much the same as with read: the $id is the [id] from the user, $data is the [dataString] that needs to be stored. Note that since we use a database you should update if no record is found and replace if there is one. Using REPLACE INTO is probably the best way to go here if you can.

Should returns true on success.

destroy ($id)
Delete a session, or at least set it to inactive so when requested with read it returns nothing. The $id parameter is once again the [id] of the session.

Should return true if your update / delete was succesfull or false on failure.

gc ()
The garbage collector for sessions (hence the name). This function should delete (or set inactive) all sessions that have an update time more then [session lifetime] seconds ago, ie, that are older than [session lifetime] seconds. Since we use a database this should be a fairly easy query:
Code (php) (nieuw venster):
1
2
3
DELETE
FROM    `sessions`
WHERE   `updateTime` < (NOW() - $lifeTime)


Note that you can set how often this gets called with ini_set('session.gc_probability', %chance); which defaults to 1 procent, ie, it gets called once every 100 pageviews. For testing you will want to increase that.

A (slightly modified) version of my usual Session Handler class can be found here, note that it requires our DB object classes so it won't run directly, but it's well documented and should give anyone still having questions a good idea how to write their own!

FragFrog out!

New comment

Your name:
Comment: