Saving PHP's Session data to a database

By Tony Marston

As you should be aware the HTTP protocol, as used for serving web pages, is completely stateless. This means that after the server has received a request, processed it and sent a response, the process which dealt with that request dies. Anything that the process had in its memory therefore dies with it, so when a subsequent request is received from the same client it is unable to refer to its memory about anything that happened previously.

Fortunately PHP provides a standard method of maintaining memory (state) between requests in the form of Session Handling functions. This allows the programmer to maintain a set of variables in the $_SESSION array which is automatically saved to persistent storage at the end of each script, and then automatically loaded back into memory when a subsequent request is received from a client which supplies the same session_id.

By default the medium used as persistent storage by the session handler will be a series of disk files, one per session, where the file name is the session_id. A file is created when a new session starts, and is deleted when the session terminates (or has expired). This is perfectly adequate for most circumstances, but it has the following drawbacks:

If you are using a shared server then other users of that server may be able to access your session files, thus compromising the security of your site.

Each server will have its own directory where these session files are maintained, so if you are employing load balancing across multiple servers there is no guarantee that a request for an existing session will be given to the server which is maintaining the state for that session.

It would be difficult for a site administrator to perform such queries as "how many sessions are currently active?" or "which users are currently logged in?"

The authors of PHP have provided the ability to store session data using a method other than disk files by means of the session_set_save_handler function. This document will show how I have used this function to store all my session data in my application database.

Within my development infrastructure it is my practice to use a separate class to access each database table. Each table class is actually a subclass to a generic table class which contains all the functionality which is standard across all database tables. This section identifies the contents of the subclass. A copy of the superclass is contained within the source code for my sample application.

This is the garbage collection or "clean-up" function. The value passed in $max_lifetime is a number of seconds. Any session record which has not been modified within this time limit will be eligible for deletion. Note that this does not mean that the session record will be deleted as soon as the time limit has expired as it depends on when the garbage collection routine is next run. With the method described in this article the garbage collection is only performed when a session closes, which means that a session can never delete its own data. If another session does not terminate then an 'eligible for deletion' session may continue to exist. If this is a problem then the gc() method must be called at the start of the read() method so that any expired data can be deleted before it is read.

As you should be able to see it is a relatively straightforward process to switch the recording of session data from ordinary disk files to a database table. This overcomes the drawbacks inherent with ordinary disk files:

The session data is more secure as a potential hacker must be able to log into the database before he can access anything.

The use of multiple servers would not create a problem as all session data now resides in a single central place and is accessible by all servers.

It is much easier to query the database should the site administrator require information about current sessions or current users.