This document describes how to customize the session handlers in PHP4. We will
provide examples of how to write a fully functional session handler that works
with DBM files and one that works with a MySQL database.
New to PHP4 was a set of native session handling functions which was badly
missing from PHP3. By default, each session is stored as a separate file
in your temporary directory (eg. /tmp in Unix). This may or may not be
appropriate depending on your requirements. For example, if you have a bunch
of web/PHP servers on different machines, you can't easily share sessions between
them (well you could save the sessions on an NFS share but that would be
slow). Another problem is that you potentially have thousands or even millions
of session files cluttering up your file system
(you run a big site right <grin>).
Fortunately for us, the developers of PHP4 were forward thinking enough
(thanks!) to provide the ability for users like you and me to extend the
session handling routines.
This document is written to explain these session handlers a bit and to
provide two working examples of how you can extend the session handlers.
Our first example will be to make the session handlers save session data
into DBM files. Our second example will have our sessions save into a
MySQL database.
Before you proceed, download the attachment and extract it into your
web document directory.
Any custom session handler we write will have to provide 6 basic functions,
they get called by the PHP4 session handler so you do not need to worry about
calling them yourself. The nice thing about all this is that your custom
session handler functions are completely transparent, so you can change them
without affec
The functions are are:
- sess_open($sess_path, $session_name);
This function is called by the session handler to initialize
things. The two parameters passed to it are $sess_path,
which corresponds to the session.save_path setting in your
php.ini file, and $session_name which corresponds to
the session.name setting in your php.ini file. More on
the duties of this function when we go into specific examples.
- sess_close();
This function is called when to when the page is finished executing
and the session handler needs to close things off. (Note, do not
confuse this with sess_destroy(), which is called to kill the
session).
- sess_read($key);
This function is called by the session handler to read the data
associated with a given session key ($key). This function must
retrieve and return the session data for the session identified
by $key. (Note: you do not have to worry about serializing and
unserializing data, if you do not know what this means, then
don't worry about it).
- sess_write($key, $val);
This function is called when the session handler has session data
to save, which usually happens at the end of your script. It is
responsible for saving the session data in such a way that it can
be retrieved later on by sess_read($key).
- sess_destroy($key);
This function is called when a session is destroyed. It is
responsible for deleting the session and cleaning things up.
- sess_gc($maxlifetime);
This function is responsible for garbage collection. In the case
of session handling, it is responsible for deleting old, stale
sessions that are hanging around. The session handler will call
this every now and then.
So now we know what functions we have to provide, they don't necessarily
have to be given those names but they have to accept those parameters
(whether you need them or not).
A DBM Session Handler
Our first example is to write a customized session handler to save session
data into a DBM file. (This is the session_dbm.php file from ying20000602.zip.)
There are many reasons why you might want to do this,
for example, if you were on a shared server from your ISP and you did not
want your sessions mixing with those from their other client's scripts.
IMPORTANT NOTE:
You must have DBM support in your PHP4 before you try this.
If you do not things can get ugly, real ugly!
The approach we are going to take is to have one DBM file that stores
all the session data (in case you don't know, a DBM file is like a very
simple database that only holds key/value pairs). To fit this into the
6 functions:
- sess_open($sess_path, $session_name);
We will open the DBM file in read/write mode by calling
dbmopen(). The name of our DBM file will be /tmp/PHPSESSID
unless you've modified the session path and name settinsg
in your php.ini file.
- sess_close();
In this function, we are simply going to close the DBM file
properly by calling dbmclose().
- sess_read($key);
Here we just call dbmfetch() to load up the session data associated
with the session key. When loading up a session, it is necessary
to make sure I'm not reading something that's been expired, so we will
attach a timestamp to the session.
Why? So that incase it has expired, but hasn't been removed out for
whatever reason, we don't accidentally read in expired data. This
would be a big no-no!
We know that DBM only stores key/value pairs, so we have to glue
the timestamp onto the value when writing the session data, and extract
it when reading in the session data. Any session who's timestamp has
been expired will be ignored. See the source code, it will make more
sense there.
- sess_write($key, $val);
To write a session, we will use the dbmreplace() function. Note
from above that we want to save an expiry timestamp on the session,
so we will attach it to the value.
- sess_destroy($key);
Destroying a session is easy, we just call dbmdelete() to remove it
from the session file.
- sess_gc($maxlifetime);
Garbage collection is a bit nasty and intensive here, what we must do
is loop through all the sessions that we've saved in our DBM file and
delete the ones that have expired. This can be slow because we must
loop through all the sessions stored in the file.
So now we've got a DBM session handler, cool! Now let's get these
sessions stored in a MySQL database.
A MySQL Session Handler
Our next example is to write a customized session handler to save session
data into a MySQL database. (This is the session_mysql.php file from
ying20000602.zip.) You would want sessions stored in a database when you have
lots of web/PHP servers and you need to share session between them (eg. if you
are serving so many users that you need load balancing). You have a bunch of
machines doing web/PHP stuff, a machine serving your normal database needs, and
another machine running a MySQL database to handle sessions. But that might be
overkill for most people :)
IMPORTANT NOTE:
You must have MySQL support in your PHP4 before you try this.
If you do not things can get ugly, real ugly!
First let's create a session database in MySQL, and then the table to
create the session table. Fire up your MySQL client and issue these
commands:
mysql> CREATE DATABASE sessions;
mysql> GRANT select, insert, update, delete ON sessions.* TO phpsession@localhost
-> IDENTIFIED BY \'phpsession\';
mysql> CREATE TABLE sessions (
-> sesskey char(32) not null,
-> expiry int(11) unsigned not null,
-> value text not null,
-> PRIMARY KEY (sesskey)
-> );
Next, modify the $SESS_DB* variables in the session_mysql.php file to
match your database setup. Make sure it all looks okay before you continue.
Our 6 functions will now work against a MySQL database:
- sess_open($sess_path, $session_name);
We need to connect to the MySQL database here using mysql_pconnect(),
and then selecting the session database using mysql_select_db(). The
$sess_path and $session_name parameters are irrelevant but we have
to keep them.
- sess_close();
We are opening a persistent connection to MySQL so we don't do anything
in this function.
- sess_read($key);
A simple SELECT statement will do the trick, we want to read the
session data for the given key, and we can specify that the expiry
timestamp must be in the future.
- sess_write($key, $val);
Writing a session is a little bit trickier. We first try to save the
session into the database using an INSERT statement. If that fails
(from a Primary Key constraint) then that means the key already exists,
so then we have to write an UPDATE statement instead.
- sess_destroy($key);
Destroying a session is easy, we just delete the session key from
the database.
- sess_gc($maxlifetime);
Garbage collection is easy as well, we just have to delete all the
expired sessions (where the expiry timestamp is in the past) from
the database.
Now we've got a MySQL session handler, pretty easy wasn't it?
Conclusion
This concludes this little tutorial, hopefully you have a good feel for how to
extend the session handling functions in PHP4. The examples here are just simple
ones to demonstrate how you would do it, extend them to accomodate your needs and
if you find any bugs, please let me know :)