Intro

The php session variable is a very useful variable system for maintaining state between calls to the server. This tutorial introduces what sessions are, why they are useful, how they work and a couple examples on how and how *not* to use them.

Why session is needed

As you may know, the http protocol is a stateless one. A request comes in from a client (browser) to the web server which then satisfies the request (if possible) and returns output to the client. CLICK--the connection closes and all is forgotten. The web server remembers nothing about the transaction that just took place and doesn't keep the lines of communications open. This frees up the web server to handle requests from other clients.

A web server with amnesia is fine for serving up static content and even for handling many programmed solutions. But at some point, we need the server to remember stuff for us--to maintain state. This is where the session comes in. The session is the flip side of the cookie. Where a cookie tells a browser to remind the server of something on each call, the session is used by PHP to store information about state on the server itself.

We need to store server side session information whenever

  • Information is too massive or cumbersome to keep passing back and forth
    • Such as a large object containing user preferences or history
    • A multi-page form "wizard" could use the session to store submitted data on each page instead of passing around several hidden fields on each page.
  • Data is sensitive and we don't want the client to access it.
    Most commonly, this is the case for authentication. If a user isn't logged in, we don't want them to be able to fake that they are by simply passing in a querystring parameter!
  • Convenience/Performance. Data that is tied to a visitor and that won't change (or won't change very often) during the user's visit could be stored in a session so that you won't need to query for it in the database each time a page is called.

Scope

  • Must be called before any headers sent
  • Super-global

In PHP a session is implemented as a super-global associative array called $_SESSION. As a super-global, $_SESSION exists anywhere in a program--it is automatically a global in all scopes (straight code, within a function, or within a method of a class, etc.) Furthermore, a specific session is automatically available and shared by all php scripts on a site. A session is unique to a specific Session ID which is passed as a cookie to a client/browser when the session is first created. In normal practice, therefore, a session is unique to a single user/browser.

Note: Unlike a real PHP array, $_SESSION keys at the root (first) level must be valid variable names.

A session is created/started with the session_start() php function. A session must be initialized before any content has been sent to the web server. This is because a cookie (transmitted in the http response header) needs to be sent to the browser with the unique session id. A session will automatically be started for you if you try to assign a value to the $_SESSION array, but if output has already been sent, this will result in a error.

Example

Starting the session:

  1. <?php
  2. error_reporting(E_ALL); // Since we're developing, we want to know if something wrong happens.
  3. echo "Sessions Test 1";
  4. if(!isset($_SESSION['visit_started']))
  5. {
  6. $_SESSION['visit_started'] = time();
  7. }
  8. $timeLoggedIn = time() - $_SESSION['visit_started'];
  9. echo "You've been on for: ".gmstrftime("%H:%M:%S", $timeLoggedIn);
  10. ?>

Execute this script a few times and you should see the amount of time increase with each refresh.

Debugging Tip:

Let's break the script in a few common ways just to see what happens. 1. Comment out line 2: //session_start(); Save and rerun the script a few times. In PHP 5.3, I get a time of zero each time the script is run. In earlier versions of PHP you may see a warning about "headers already sent".

Expiration

Sessions expire after a set number of minutes. Session time-out can be set in php.ini

Example 2:  Creating a multi-page form using session variables

A common need that arises is to take a long web form and break it up into logical "pages."  Sign-up forms, surveys, CMS installers, and long configurations often use this wizard approach. The wizard enables the following features:

  1. Breaks up an html form into multiple, discreet steps
  2. Keeps track of the data submitted in each step and in all the steps taken so far.
  3. Allows the user to advance to the next/later steps.
  4. Validates each step as it is submitted, allowing access to following steps once a step has been tested.
  5. Lets a user go back to previous steps.

As a programmer, there are a few different approaches you could take to manage the data submitted in each step.  One approach I used in the past was to have many hidden input fields in each step so the POST would always contain all the data accumulated so far.   This approach, however, creates a LOT of extraneous HTML and is rather inflexible.  It also leaves your form vulnerable since a user could hack the hidden fields once they've passed earlier validation.

Another approach would be to temporarily store the user's responses on the web server using PHP sessions.  That is the method I will use for this example.  See Listings 2.1 and 2.2.

Listing 2.1 is a very simple class that acts as a wrapper for accessing and managing the form's data.  The class lets us manage multiple wizards/forms by allowing the programmer to give each wizard its own name.  It lets us treat the session contents as properties of a class which is easier to read, reduces the possibility of transcription errors and conceals the underlying implementation.

$_SESSION, as stated earlier, is an associative array.  In this wizard an multidimensional array is created in the session to store the data.  The first dimension of the array is a unique name for the wizard.  This allows us to have multiple wizards on the same site that won't collide if a user is visiting multiple places on your web site in the same browser.  The following dimension(s) of the array store the data submitted by the form's user.  So on form 'survey' the question called 'first_name' is stored as $_SESSION['survey']['first_name']as a string. If we add some checkbox options to our form for favorite pizza toppings, we can store those pizza toppings as an array in $_SESSION['survey']['pizza_toppings']. 

Listing 2.2, wizardExample.php implements a very simple wizard using the FormWizard class.  On each step, it uses print_r() to display what is stored in the session and what was last submitted via POST.

 

Listing 2.1 - FormWizard.class.php

A class that makes use of PHP sessions to manage multiple page forms/wizards.

Listing 2.2 - wizardExample.php

A simple example of using sessions to create a multi-page form, possibly useful as a survey. Also see the listing for the Form Wizard class.

How NOT to use SESSIONs

Since sessions are sitewide, per user/browser, do not use them to replace information that should be conveyed by a URL.   If you visit two different URLs on the same site and a session variable needs to change because of a visit to one of them, consider, what is the affect on the other location(s).  Don't depend on a session variable for keeping track of which section of a site is being visited, for example.  Simultaneously visiting another section of the site (with the same browser) could then change the session causing unpredictable results.

I hope this tutorial has been helpful in explaining some uses of $_SESSION and why it is useful.  Share your questions or comments with me.