This tutorial is designed for an advanced PHP programmer. It assumes you know
how to handle cookies. (See Feedback with a Cookie
to learn about using cookies.) You should also know how to pass data from one
page to another using the POST and GET methods.
Unlike PHP 3, PHP 4.0 has built-in capabilities to handle session management.
The session management functionality in PHP 4.0 is easy to use, powerful and
open for custom modifications. Creating sessions allows you to keep track of
the actions of a particular user over the period of time she is viewing your
To associate session data with a user, you need a session identity number,
that is, a key that ties the user to his data. This tutorial discusses how to
open sessions, track session data, and clear the data when you no longer need
PHP’s Built-in Session Library
Luckily, PHP 4.0 has basic session management built in, which frees you from
the task of inventing session IDs, serializing and storing session data. While
it’s very easy and straightforward to use and may suffice for your needs, it
lacks some of the advanced features that the PHPLib provides.
In this tutorial you can learn the following:
- What a session is
- How to use persistent variables
- How session IDs are passed from page to page
- How to end a session and handle clearing of data (garbage collection)
- How to register variables to refer to during user sessions
- How to use the PHP 4.0 session management functions, including:
- How PHP stores session data.
Session management is a mechanism to maintain state about a series of requests
from the same user across some period of time. That is, the term “session” refers
to the time that a user is at a particular web site. The problem is, that HTTP
has no mechanism to maintain state. Individual requests aren’t related to each
other. The Web server can’t easily distinguish between single users and doesn’t
know about user sessions. Session management refers to the way that associate
data with a user during a visit to a Web page. This tutorial uses the term session
for a single visit of a user. For example, a typical online shopping session
might include logging in, putting an item into the shopping cart, going to the
checkout page, entering address and credit card data, submitting the order,
and closing the browser window. PHP 4.0 includes native session management functions
to ease the task of managing user sessions.
The “life: of a session refers to the amount of time the session is active.
“Serializing” means the transformation of variables to a byte-code representation
that can be stored anywhere as a normal string. Without the serializing feature,
it wouldn’t be possible, for example, to store PHP arrays into a database. Serializing
data is very useful for preserving data across requests, an important facet
of a session library. You can use
but note that in PHP 3 these functions don’t work correctly on objects (classes);
class functions will be discarded.
PHP’s session management library offers the key characteristics required of
a session management library:
- It stores session data on the server. Because the library uses different
storage modules, you can keep the data in plain text files, shared memory, or
databases. The exact location of data is not really important (as long the
performance of the medium is sufficient).
- It uses a cryptographically random session ID to identify a user.
- It saves the session ID (and only the session ID) on the client side using
cookies, GET/POST, or the script path. (The PHP library provides all of these
methods; we show how to use them a little later.)
- If the user disables cookies, the application can use other means of
To associate session data with a user, you need a session identity number: a
key that ties the user to his data. PHP 4.0’s session management frees you from
the task of inventing session IDs, serializing and storing session data.
something beyond the standard PHP session functionality.
Starting a Session
A PHP 4 session is started either explicitly by
or implicitely by registering a variable for the session, using
Usually, you will call
session_start() on top of the page, so that
session variables are available to your script, and register variables to the
session later in the script. It wouldn’t make a difference though, if you registered
your session variables with
session_register() in the head of the
script and left out the
session_start() call –
session_start() internally, if the session isn’t started
yet. When you start a session either way, the following happens:
- PHP checks whether a valid session ID exists.
- If there is no session ID, PHP creates a new ID.
- If a valid ID exists, the frozen variables of that session are reactivated
and introduced back to the global namespace.
Registering a session variable is done through the
command. This allows you to create (register) variables which are stored throughout
the session, and can be referred to during the session. All variables you want
to preserve across page requests must be registered to the session library with
session_register() function. Note that this function takes the
name of a variable as argument, not the variable itself. You can use
to remove variables from the session, for example, when the user removes a product
item from the shopping cart.
This is an example of a counter.
- Start a session
- Print the most recent value of the counter
- Increment the counter
- Register the counter
Of course, this example is different from a normal page counter: the session
(and thus the counter) is tied to one specific user. With PHP’s default
configuration, the session cookie has a lifetime of 0; if you close the browser
and reopen it, the counter restarts from zero, as the cookie has been deleted.
- Register the variable $foo
- Register a previously defined variable $bar
$bar = "This is a string";
$foo = "bar";
The difference in the last two syntax examples is that in the first a
variable named “foo” is registered as session variable, in the latter actually
a variable named “bar” is registered. Session_register() takes the name of a
variable as argument, not the variable itself – this is easily confused, but
the examples show the difference clearly.
It’s as easy to handle session variables as it is to handle GET/POST variables.
If you register a variable named foo, $foo is accessible automatically after
calling session_start(). Because the serialize() function was improved in PHP
4, it’s also feasible to treat objects (classes) as session variables.
Note: At the start of a session, a new ID may be created if the session is
refused and marked as invalid because the HTTP referrer for the page comes from
a non-local site and extern_referer_check (note the single “r”) is enabled in
the PHP configuration. This introduces some additional security, as it prevents
users coming from other PHP sites taking over a session (which is still highly
improbable, however, due to the algorithm used for the generation of the
See also Ending a Session
Ending a Session
Session ending is not automatic, because it is difficult for the system to tell
when the user is finished the session. Several commands help you control how
the system determines when to end a session for a user.
- You can force a session end with the command
- If you propagate the session ID via cookies, the default cookie lifetime is
0, meaning that the cookie is deleted as soon as the user closes the browser.
You can influence the cookie’s lifetime with the configuration value lifetime.
- You can use the
gc_maxlifetimeconfiguration directive to determine
how long after the last access to this session the data should be destroyed.
This is used because the server doesn’t know whether the cookie still exists
on the client side. However, performing such a cleanup of old sessions (called
“garbage collection”) on every page request would cause considerable overhead.
Therefore, in tangent with the
gc_maxlifetime, you should use
gc_probability. This specifies with what probability the garbage
collection routine should be invoked. If gc_probability
is 100, the cleanup is performed on every request (that is, with a probability
of 100%); if it’s 1 as by default, old sessions will be removed with a probability
of 1% per request.
need to pay special attention to the garbage collection routines. Users might
bookmark URLs containing the session ID, so you need to make sure that sessions
are cleared frequently. If the session data still exists when the user accesses
the page with the session ID at a later time, PHP simply resumes the previous
session instead of starting with a new session, which may not be your intention.
A value of 10 to 20 for
gc_probability would better fit this scenario
than the default value of 1.
You might ask yourself why PHP allows you to specificy a probability (
which determines when garbage collection will occur, rather than a function
which cleans up every n times. If PHP used a counting function, the server would
need to track the number of opened sessions somehow. Using the probability function
means that the server does not have to store counters for cleanup, which translates
to cleaner and faster execution.
To read and save session data, PHP uses storage modules, thus abstracting the
back end of the library. There are currently three storage modules available:
Files.By default, PHP uses the files module
to save the session data to disk. It creates a text file named after the
session ID in /tmp. You probably won’t ever need to access this file directly.
In the example of the session counter, the content of this file would look like
this, which is a serialized representation of the variable:
mm.If you need higher performance, the mm
module is a viable alternative; it stores the data in shared memory and is
therefore not limited by the hardware I/O system.
User.Used internally to realize user-level
callback functions that you define with
The real power lies in the capacity to specify user callbacks as storage
modules. Because you can write your functions to handle sessions while still
being able to rely on the standardized PHP API, you can store sessions wherever
and however you want: in a database like MySQL, XML files, on a remote FTP
server (an FTP server is unlikely, but you get the idea).
session_set_save_handler() takes six
strings as arguments, which must be your callback functions.
The syntax of the function is as follows:
void session_set_save_handler(string open, string close,
string read, string write, string destroy, string gc);
To leave out one argument, pass an empty string (“”) to
The functions are defined as follows:
bool open (string save_path, string sess_name);
This function is executed on the initialization of a session; you should use it
to prepare your functions, to initialize variables, or the like. It takes two
strings as arguments. The first is the path where sessions should be saved. This
variable can be specified in php.ini or by the
function – you can use this variable as a joker and use it for module-specific
configuration. The second argument is the session’s name, by default PHPSESSID.
Returns true on success and false on error.
bool close ();
This function is executed on shutdown of a session. Use it to free memory or to
destroy your variables. It takes no arguments and returns true on success and
false on error.
mixed read (string sess_id, );
This important function is called whenever a session is started. It must read
out the data of the session identified with sess_id and return it as a
serialized string. If there’s no session with this ID, an empty string “” is
returned. If there is an error, false is returned.
bool write (string sess_id, , string value);
When the session needs to be saved, this function is invoked. The first
argument is a string containing the session’s ID; the second argument is the
serialized representation of the session variables. This function returns true
on success and false on error.
bool destroy (string sess_id, );
When the developer calls
session_destroy(), this function is executed.
It destroys all data associated with the session sess_id and returns true on success
and false on error.
bool gc (int max_lifetime, );
This function is called on a session’s start-up with the probability specified
gc_probability. It’s used for garbage collection; that is, to
remove sessions that weren’t updated for more than
seconds. This function returns true on success and false on error.
If you want to setup your own storage modules, for example to store session
data in a MySQL database, you need to provide PHP implementations of these
functions. The prototypes will look similar to these examples:
function sess_open($save_path, $sess_name)
function sess_write($sess_id, $val)
To register these calback functions, you use
session_set_save_handler(“sess_open”, “”, “sess_read”, “sess_write”,
PHP 4 sessions support the following methods of passing the session ID:
- Cookies (default)
- Hidden in the URL, either done manually or by automatic URL rewriting
Cookies are the default way to pass the session ID between pages. If you’re
happy with cookies, you don’t have to worry about any special configuration.
Another common way is to pass the ID is with GET/POST. Your URL would then be
script.php3?<session-name>=<session-id>. You can create such URLs by
using the global constant SID:
Automatic URL rewriting is one of the very cool new features of PHP 4, allowing
you to add the session ID to all the links within the page. To enable it, you
need to configure PHP with
--enable-trans-id and recompile it. Then
the session ID in the form
links within your PHP-parsed pages. While this is a handy feature, it should be
used with caution on high-performance sites. PHP has to look at each individual
page, analyze it to see whether it contains relative links, and eventually add
the ID to the links. This obviously introduces a performance penalty. Cookies,
on the other hand, are set only once, avoiding the overhead of URL rewriting.
The following is completely commented sample code.
The popular hangman game is a great way to show how to use persistent
variables. In this game, the computer chooses a random five-letter word and the
player needs to figure it out by choosing letters to fill in. The user has only
six guesses, or he’ll end up on the gallows. We’ve chosen a database of common
English female names, but you’re free to use any other word list you want.
Simply replace the existing words.txt file with your own version; the only
constraint is that each word must be on one line.
Of course, this game cannot work without keeping state information. the player
would always have five tries left, could never win without guessing the whole
word correctly the first time, and generally, it wouldn’t be much fun at all.
If you think for a moment about the game’s logic, you’ll come up with three
variables that need to be remembered from request to request:
- The random word the user is to guess.
- The characters the user has already guessed.
- How many tries have failed so far.
The number of tries could be calculated with some tricks, but for clarity’s
sake this example stores it separately.
The example uses the default method of passing the session ID, cookies, so no
tricks are necessary in the use of the session library. It follows the
following program logic:
- The three session variables are registered.
- The script checks whether the form is invoked by a Post operation, meaning
that the user has submitted a guess.
- If this is the case, the script processes the input, updates the game state
(won, lost, correct guess, incorrect guess) and outputs a message accordingly.
- If not, a new game is started, and a random word is extracted from the file
- A string, which hides the not-yet-guessed characters in the guess word, is
created and printed to the browser.
- The rest of the page is drawn.
All HTML output is handled by a separate template class. This allows the separation
of code and layout needed often in professional web applications, but that will
be the topic of another tutorial.
The code is simple, but easy to understand therefore and can give you a good
idea how and for what tasks to use the session library. And you could even
extend the application; for example, you could calculate the player’s highscore
and store it in a database. If you do such fancy things with this game, be sure
to let us know and we’d be happy to feature your versions on our web site!
The code contains comments preceded by “//” marks.
$guess = strtolower($guess);
die("Could not open file \"$file\" fo reading.");
// Get file size
$size = filesize($file);
// Init randomizer, get a random value in the range 0..filesize
// Seek to a random position in the file - possible this is EOF.
// If line was empty, try again
$line = hang_get_random_line($file);
// Return random line
// Initialize session
if($REQUEST_METHOD == "POST" && !empty($word) && !empty($guess))
$guessed_chars = $guess;
// Character not found - one try less left
$message = "Wrong guess.";
$message = "Correct guess!";
$word = strtolower(hang_get_random_line("words.txt"));
$message = "Welcome to Hangman!";
$num_of_tries = 1;
$guessed_chars = array();
$guessed_word = $word;
// Construct the template guess word ("_" in place of not-yet-guessed characters)
for($i=0; $i<strlen($word); $i++)
$guessed_word = str_replace($word[$i], "_ ", $guessed_word);
$button = "Go";
// Check whether the user has won or lost the game
if($guessed_word == $word || $word == $guess)
$message = "Correct guess - you've won!";
$message = "You've lost. The word was \"$word\".";
$button = "Try Again";
$num_of_tries = HANG_MAX_TRIES;
// Create new template instance
$tpl = new EasyTemplate("template.inc.html");
// Assign template variables
$tpl->assign("GUESSED_CHARS", @implode("", $guessed_chars));
// Output template
Tobias Ratschiller is a New Media Consultant in Italy, specializing in the
creation of large scale dynamic websites.
He has provided consulting and implementation work for some of the world’s
largest websites and has contributed to several PHP titles.
Together with Till Gerken, he’s currently writing a book titled “Advanced Web
Application Development with PHP”, which will be published in July 2000 by New
Apart from that, he teaches at seminars about usability, user interface design
and content management systems.
Tobias runs http://phpwizard.net/