Building my PHP Session Handler

My homework recently consisted of building my session handler, which confused me greatly – what on earth is session handler? At first glance, I wondered why would one use session handler? How is different from, say, calling the method by $session->getData()? Took me a while, but I finally got a working code that I have now recorded on Github, and I got some basic idea on What, How, and Why.

Note that this is really a blog where I store my notes for future references and to type out information so my mind can wrap around things. There is a lot of “typing whatever comes to mind” and cherry-picking only things that interest me. If you somehow wandered here looking for organized info on Session Handler, I suggest the tutorial on Sitepoint, which is way more organized and correct.

What is Session Handler: Like its name, it handles session. When a session starts, such as via session_start(), data are stored in $_SESSION with a configuration file php.ini, or at least that is my impression of how it works. Using those information and configuration settings, the handler manages database storage. Its basic, possible use includes opening database, reading the database and outputting the data, writing to the database with the values gain from $_SESSION, destroying selected data from database, performing garbage collect in the database, and closing the database.

How to do a Session Handler:

Class Session {   // Or whatever you name it as.

// I am using the constructor in PHP 5 style. Do not misspell it as constructor. Certain someone spent a whole night wonder what is wrong with her constrictor because of it…

function __construct() {

// The build-in function below “sets the user-level session storage functions” (via php.net), which pretty much means that it designates when the methods in this Class is invoked. Yes, the methods are invoked automatically basing on the condition! Most of the time anyway. Do not misplace the order of the arrays, or your function will be invoke in the wrong condition.

// Placing it inside the session class constructor is optional. However, placing it outside the class would mean you would type it out each time the class is invoked, plus “$this” will be change to the name of the object created by the Class, which is just annoyingly repetitive.

session_set_save_handler(   

array($this, ‘open’),    // 2nd parameter’s name is personal preference, but pick something easy to understand. ‘Open’ is pretty standard.

array($this, ‘close’),

array($this, ‘read’),

array($this, ‘write’),

array($this, ‘destroy’),

array($this, ‘gc’)

);

session_start();   // though not required, it’s good idea to place session_start() her so you don’t to invoke every time you create an Object with this class.

}

function open() {

// Invoke condition: whenever session is starting, such as when session_start() is used.

// Typical content: call to database.

}

function close() {

// Invoke condition: after write() was called or when session_write_close() is called.

// Typical content: close database.

}

function read($sessionId) {   // all method’s parameter seems to be optional. Each method’s first parameter calls the value from $session_id(). You as the coder don’t have to do anything other than call the Class (or session_start() if it is not in the Class’s constructor. See, this is why its good to put session_start in the constructor) unless you want to change the default session id. You should not have to type read(1234) or something like that.

// Invoke condition: whenever session starts or when session_start is called() – but after open().

// Typical content: what you want to display from the database.

}

function write($sessionId, $data) {   // like read(), $sessionId will call the value from $session_start(), while $data will call the value from $_SESSION[‘data’]. Again, you don’t have to do anything other than calling the class unless you want to change the default value. I change the $data in my handler to take in the input value, but I did it by reassigning the value in $_SESSION[data] outside of the class ($_SESSION[‘data’] = $_POST[‘something’]) and not by $data = something.

// Invoke condition: whenever the PHP shuts down or when session_write_close() is called, but after the output stream is closed. close() is executed after this.

// Typical content: writing to database. Note that $_SESSION[‘data’] is automatically serialized. This means you have do some unserializing and serializing, plus you have to make sure to prevent SQL injection. In my own code, I:
(1) Copy the serialized session $_SESSION in a different variable, $original.
(2) Unserialized $_SESSION. Note that after PHP 5.3, using unserialize() on a SimpleXML_Load_String() will result in an error message, which is what will happen with $_SESSION. Use session_decode() instead.
(3) Store the unserialized content in a variable $output, then real_escape_string() it to prevent SQL injection.
(4) Restore $_SESSION with the variable containing the serialized session ($_SESSION = $original).
There are other methods, but this is the quickest one I can understand – I am working on a deadline after all.

}

function destroy($sessionId) {

// Invoke condition: whenever the session is destroy, either via session_destroy() or with session_regenerate_id() set to parameter TRUE.

// Typical content: what happens if a session is destroy. In my case, I set my codes to do a session_destroy if a submit button “Logout” is press (AKA, check if a $_POST[‘logout’] exist, if so, call session_destroy() ). When the destroy() is invoked as a result of that, it remove the entry in my database associated with the current session id.

}

function gc($lifetime) {   // $lifetime calls the value store in session.gc_maxlifetime.

// Invoke condition: called periodically by PHP, with the frequency based by session.gc_probability and session.gc_divisor.

// Typical content: what happens if a session is garbage collected. In my case, in my construct(), I set the session.gc_maxlifetime to 15 minutes. My database contains a column, ‘time’, that stores the time the entry was first written. When gc() is invoked, if any rows have a ‘time’ cell older than 15 minutes ago, the row is removed from the database. In another word, a user is automatically logged out after 15 minutes with its session id and data removed.

}

Why use Session Handler: It is probably because it (1) reduces the amount of coding when you store session repetitively and (2) sets a lot of automation.

When I first started building the code and my constructor wasn’t working, I placed session_start() outside of the class. I also attempted to invoke the methods manually:

$session = class Session();

session_start();

$session ->open();

$session -> read();

$session -> close();

That is a lot of code to be typed each time you invoke a session class. With the session handler, all the methods are invoked automatically when conditions are met. Even the parameters, like $sessionId, $data, and $lifetime that I mentioned earlier, are automatically set. Coder can change them by change the values in $_SESSION[] or session.gc_maxlifetime, but it’s pretty automatic.

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.