Session Tracking: Part I

The ability to gather, analyze, and implement information about visitors to your organization's web site is one of the most powerful aspects of this new media. The advantages of doing this are manifold -- this information is not only useful for analyzing the patterns of visitors who are interested in your products and/or services, but also allows you to provide customized services to these visitors. For example, not only could you learn which pages are most popular with French users, but you could also automatically recognize these users and provide them with a welcome message in French.

This type of customized service has become very popular. For example, Weather.com allows you to view only what you're interested in viewing. This is great, because I'm a weather nut -- I go to the site so much that I would rather not have to waste time navigating around to the various parts of the site when I can just look at everything I want to see on one page. It can also customize each page to my tastes as I navigate through the site, further tailoring content -- even in areas that I have not specifically customized.

In this article, I will explain how you can begin creating your own customized web sites using PHP's session-tracking functionality. It's extremely easy to use, and very useful for creating customized Web applications. Before delving into the functionality, I'll begin by presenting a few introductory concepts.

Configuration

PHP's session-handling features, first introduced in the 4.0 release, are native and thus require no additional packages other than the PHP distribution. I've had the opportunity to use sessions extensively on both non-Windows and Windows-based servers, and have not run into any compatibility problems thus far. However, there are a few configuration issues that you should keep in mind if you decide to use this cool feature. In this section, I'll present these issues, and will discuss others as applicable later in this article.

Configuration of PHP's session-handling feature takes place in the php.ini file in the section aptly titled "Session." There are currently 19 configuration directives found in this section, some of which are more important than others. I'll discuss the most important directives here:

session.save_handler (files | mm | user)

PHP supports three methods for storing and retrieving session information: within flat files (files), using shared memory (mm), and through user-defined functions (user). Storage within files is the most commonly used method, mostly because it's the default configuration setting.

Although this is sufficient for most situations, it's important to keep in mind that the number of session-storage files could quickly rise into the thousands and indeed, even hundreds of thousands depending on the number of site visitors. Shared memory is likely to be the fastest of the three methods, but is volatile because this information could easily be erased. The creation of user-defined functions is the most flexible of the three methods, but is also the most complicated. This method allows you to create custom storage and retrieval handlers, making it possible to store the session data within any PHP-supported media, such as an Oracle or MySQL database.

To use one of the three methods, you must set session.save_handler accordingly: files for file-based handling, mm for shared memory, or user for user-defined functions. For purposes of this article, I'll assume that you've left it at the default, files.

session.save_path (path/to/directory)

This directive is only useful when session.save_handler is set to files, as it is used to specify the location where the session files are to be stored. I would recommend setting this directory somewhere outside of the document root to ensure that the files can't be viewed through a browser. Furthermore, ensure that the directory can be written to and read by the user running PHP (probably "nobody").

session.auto_start (0 | 1)

This directive determines whether session-handling will be automatically initiated upon request. Since it's unlikely that you'll use sessions within every section of your site, this is by default set to 0. However, if you'd like to enable automated session support, set this directive to 1.

Of the 19 configuration directives, only the above three are of a general
enough nature to be discussed without learning more about PHP's session-handling strategies and features.

Session-propogation

Basically, a session can be defined as the timeframe in which a visitor
navigates your web site. PHP is capable of tracking a visitor throughout his session by assigning a unique session identification number (SID) to that visitor. Although you can create SIDs in various ways, a default SID created by PHP might look like fc94ad8b1ee49ef79c713ee98ac1fcc4. There are two ways in which the SID can "follow" the user:

Storage and subsequent retrieval in a cookie

Rewriting of the URL to include the SID parameter

I'll discuss each strategy and its configuration directives in the following sections.

Cookie usage

Of course, this is likely to be the preferred method to track users because it is the easiest way to create a state of persistence between user sessions. However, keep in mind that some users might have cookie support disabled in the browser, or might be using a browser that is not capable of implementing cookies.

There are a few configuration directives found within the php.ini file that should be examined before attempting to use sessions and cookies. I'll present each here:

session.use_cookies (0 | 1)

This directive specifies whether or not cookies are to be used to store
SIDs. A 0 disables cookie usage, while a 1 enables cookie usage.

session.name (Default: PHPSESSID)

This directive specifies the name of the cookie that stores the SID. The default is PHPSESSID.

session.cookie_lifetime (Default: 0)

This directive refers to the number of seconds that the cookie will "live" after it is first created. The default is 0, which results in the cookie expiring at the end of the session.

session.cookie_path (Default: /)

This directive specifies the domain path for which the cookie is valid. The default is /.

session.cookie_domain (Default: null)

This directive specifies the domain for which the cookie is valid. By
default, this directive is simply set to null, which in this case means
whitespace.

Keep in mind that if session.use_cookies is enabled, there is no need for you to explicitly call a cookie-setting function (set_cookie(), for example). PHP's session-handling functionality automatically does this for you.

Rewriting URLs

Rewriting a URL to include an SID is a bit uglier than using
cookies, however it is also somewhat more foolproof, as it may not always be possible to use cookies.

The SID can be appended to a URL either manually or automatically. To manually append the SID, all you have to do is include the SID global reference within the URL, like so:

<a href="configure.php?<?=SID?>">Go to the configuration page</a>

Of course, manually attaching the SID is not always the most convenient way to do things. Therefore, you can also ensure that it is automatically appended by compiling PHP with -enable-trans-id. In doing so, you will not have to include the <?=SID?> within the URL, as it will be automatically placed there.

Let's get to session-tracking already!

By now I'm sure you're just itching to begin creating user sessions. Have no fear! In this section I'll introduce several examples that should provide you with a basis for building your own session-oriented applications using this cool feature.

A simple example

In the first example, I'll demonstrate how an SID is created and how a
session variable is stored for later use. Consider a scenario where you
would like to grant the user the possibility to choose their own background color. This background color will then be stored and used throughout the various other pages found on the web site. For sake of simplicity, I'll just hard-code the value of the $bgcolor variable ("#8080ff") into the script. Furthermore, I'll assume that cookie support is enabled and is supported by the client browser.

Welcome to a session-enabled page! The background color on the next page
will be set to a stylish blue.<p>
<a href = "1-2.php">Go to another session-enabled page</a>.
</body>
</html>

Clicking upon the link provided in Listing 1 takes the user to Listing 2 (1-2.php), shown below. The purpose of Listing 2 is to demonstrate that the cookie has been set and the SID can be retrieved from it. Also, this script retrieves the value of the session variable $bgcolor, displaying it both as the page background color, and within a string.

Note that if the session.cookie_lifetime had been set to 3,600 seconds for example, both the background color and the SID would persist for one hour after the initial arrival at Listing 1, regardless of how many times the user leaves and
returns to the site during that timeframe.

Deleting session variables

Sometimes it is necessary to delete session variables. This is easily accomplished with the function session_unregister(). For example, suppose you provide the user with the opportunity to deny the automatic setting of the background color to #8080ff as was done in Listing 1, instead causing the default white background color to be displayed. To illustrate how this is accomplished, I'll rewrite Listing 2, the result of which is shown in Listing 3:

Storing session variables in a cookie

The final concept I'd like to discuss is how to store several parcels of data within cookies on the client machine. Certain browsers place limitations on the number of cookies a domain can store at one time, therefore it becomes necessary to devise other techniques for storing this data. One such technique is to encode all the data into one long string and store it within a single cookie. Not surprisingly, those brilliant PHP developers had the foresight to create a function capable of doing exactly this, namely session_encode(). This function will return a single string containing all of the variable names and matching data, much like you would see appended to a URL. Consider Listing 4 for an example:

This is particularly convenient because you can then store this string
directly within a single cookie. The only thing you must be wary about is the overall cookie size, since most browsers support maximum cookie sizes of only around 5 kilobytes. To ensure the data is not erased (unintentionally or otherwise) by the user, you might want to store this string within a database and store only the session ID in a cookie on the client machine. Or, you could store the SID within the cookie and the encoded string within the database. Just keep security in mind in accordance with the sensitivity of the data being stored on the client browser. Still another alternative is to store the encrypted string in a cookie, and then decrypt it upon retrieval.

Regardless of what you decide to do with the data, you can later "unravel" the string and automatically restore the session variables by using the function session_decode(). Supposing you wanted to later decode $encoded_string:

<?
session_decode($encoded_string);
?>

This not only decodes the string into its respective name/value pairs, but it also makes each a session-variable.

What's next

This article introduced you to PHP's native session-tracking functionality. Details were provided regarding general configuration, strategies (cookies vs. URL rewriting) and PHP's predefined session functionality. To illustrate this useful feature, several examples were provided, giving you a taste of how sessions are used in a typical scenario.

In my next article, I'll expand upon this introduction of session-handling,
focusing on how you can use PHP's session_set_save_handler() function to create customized session-storage functions. This is particularly useful when you would like to use a specific media for storage and retrieval of session information, such as a database. To illustrate this great feature, I'll explain how custom functions can be written which act to incorporate a MySQL database into the session-storage scheme.

W.J. Gilmore
has been developing PHP applications since
1997, and is frequently published on the subject within some of the Web's
most popular development sites. He is the author of 'A Programmer's
Introduction to PHP 4.0' (January 2001, Apress), and is the Assistant
Editorial Director of Web and Open Source Technologies at Apress.