My first experience with WordPress was when a client asked me to hack apart the registration system to allow for simple custom referral links. They wanted users to be placed at different user levels depending on the URL they used to sign up for an account.
My initial attempt was … atrocious When a user hit a referral link, I used a hook to change the default user level, then changed it back after they registered. The problems with this approach are so glaring, I won’t bother explaining them. Seriously, it was a stupid idea.
My refined attempt tried to hack WordPress to add PHP session support. The redefined user level was stored in the [cci]$_SESSION[/cci] superglobal and pulled back out upon registration. Less stupid, but still not very elegant.
The Problem with Sessions
Split Servers
I came to despise sessions the first time I worked with a distributed system. Basically, the system was composed of two web servers positioned behind a load balancer. Both web services pulled information from the same database. When you requested the domain, the load balancer would forward your request to whichever server was under less of a load. It was fast and efficient. But we consistently had problems logging in.
The issue was that both webservers handled their sessions internally, and authentication was session based. You could be logged in according to one server and be moving along just fine. Then, on a subsequent request when the load balancer moved you to the other server, you were no longer logged in.
Queue months of headaches and debating session handling with the IT guys.
Validation
When you’re using a normal PHP [cci]$_SESSION[/cci], there’s a session cooking stored in your browser that gets sent with every request. The server reads this cookie, finds the appropriate session file on the server, unserializes the data, and populates the superglobal. Unfortunately, there’s no way to verify that you are actually the owner of the session.
The chances of someone guessing your session ID are miniscule, but possible. All they’d need to do is spoof your session ID and voila, they’d have access to all of your session data as well.
Use Case in WordPress
I can hear you saying now, “so what?” You’ll probably never want to use sessions in WordPress. But I can think of a few situations where either [cci]$_SESSION[/cci] is already being used or where it would be hugely useful.
Shopping Carts
Just about every quality shopping cart solution I’ve seen for WordPress uses sessions or some form of custom server-side data store based on them. It’s important to keep the actual cart and purchase information on the server to protect it from tampering.
Per-User API Caching
Recently I built a project that requested large chunks of appointment information from a remote API. This is somewhat sensitive data, requested over SSL to protect it from prying eyes, and specific to each user so it can’t be cached in a generic WordPress option. Originally, I passed the API response through to a cookie so it would live in the user’s browser (the data needs to be presented across multiple pages). However, cookies have a finite size and some larger responses were being lost.
Instead, I ended up creating a transient with a unique ID for every response and storing this unique ID in a cookie so WordPress could map cached data to the user later. Wait, that sounds exactly like a PHP session …
A Proposal
I propose adding an object to WordPress. Something that looks and feels a lot like [cci]$_SESSION[/cci] to developers, but takes advantage of WordPress’ database model and caching systems.
Essentially, every visitor will be issued a session by something like [cci]wp_session_start()[/cci]. This session will be identified by a key stored as a browser cookie. It will also be validated against the visitor’s IP address (stored in the [cci]WP_Session[/cci] instance itself).
Each [cci]WP_Session[/cci] object will act as a key-value store (similar to [cci]$_SESSION[/cci]):
// Start a session. This can be called directly or hard-coded
// into WordPress' init functionality.
wp_session_start();
global $wp_session;
$wp_session['string'] = 'This is a string';
$wp_session['object'] = new stdClass();
$wp_session['array'] = array();
// Write out the session. Can be called directly or hard-coded
// into WordPress' shutdown functionality.
wp_session_commit();
Storage
The actual data in a WordPress session object will be stored in a short-lived transient. The expiration date of the transient will be advanced every time the object is touched (either a read or a write) because it’s still active. It will essentially just be a serialized associative array and can store just about anything WordPress needs ot to store.
The advantage of using transients (which are just WordPress options) is that they can be backed by memcached in certain optimized configurations. Also, the session data will always be available where WordPress’ data is available since they both exist in the same place.
Thoughts?
Not everyone will have a use for sessions when developing with WordPress. But having a standard, core object people can code against would be useful. Is this something you could see yourself using? When, where, and why? Is this something that should be baked in to core to be available to all, or should it remain plugin territory?