Php Sessions
— print (last updated: Feb 24, 2009) print

Select font size:
Download the PhpSessions.zip archive. Install it into your default website folder and set it up as a NetBeans project as done in Php Basics.

Session Management

Session management is a mechanism for maintaining and sharing the state of variables (called session variables) for every participating program in a web project. These variables are not lost when you go offsite and return. This is one of the key ingredients of a web-based shopping cart used in e-commerce.

The server can maintain a relationship with a browser session by sending and receiving information packets called cookies. A cookie is simply a name/value pair of data which contains other attributes such as the target URL (server name and path) and expiration timestamp.

In session management using cookies, when a browser first contacts a web server, the server sends a cookie called the session id which is then stored in the browser. Normally the session id is some fixed-length "random" sequence of hex digits which the server uses to identify the browser connection and associate some persistent information. When the browser makes a subsequent contact to the server so that the cookie's URL matches the server URL, the cookie is sent to the server.

Session handling is built-in to Php using cookies whose name is PHPSESSID. As mentioned above, the cookie is originally sent from the server to the browser and then subsequently sent back to the server for all future contacts to that site during the current browser session. The default lifetime for a PHPSESSID cookie is the browser session, i.e., as long as the browser remains open.

Php session management

A Php program begins session management by calling the function:
session_start();
From this point onward the $_SESSION array represents the browser session and can be used to keep track of any number of variables via user-determined keys. The session_start function must be called prior to the echoing of any HTML code; in particular any file in which this is used must start with
<?php
as the very first characters in the file, i.e., with NO other characters (even whitespace) prior to this notation. Once a session has been established and we set
$_SESSION['name'] = /* some serializable value */;
and then $_SESSION['name'] becomes available to all other participating scripts. To invalidate a session variable simply unset it:
unset($_SESSION['name']);
or, to invalidate all session variables:
session_destroy();

Content of the session files

For a better understanding of how this is working, look at the session files themselves. They are stored in the temporary directory specified by session.save_path in the Php init file (in recent Ubuntus, the directory is /var/lib/php5). In Linux, these files are owned by the Apache user and so you have to be root to read them (which is good!).

The session files are of the form:
sess_<value of PHPSESSID cookie>
like this: sess_71c3cf38b232720002c25fd7919066e5. The content is a string created by serializing the $_SESSION array with the Php serialize function. For example,
serialize( array( "xx" => -15, "yy" => array(3,4) ) ) = 
	"a:2:{s:2:"xx";i:-15;s:2:"yy";a:2:{i:0;i:3;i:1;i:4;}}"
A Php program which uses sessions obtains the stored values by de-serializing the session using the Php unserialize function.

Controlling the path of the session

By default, the path of the PHPSESSID cookie is "/", meaning usually that the cookie will be sent to anywhere within the domain. If you want to restrict the path to the directory in which these scripts are defined, you need to use the session_set_cookie_params function prior to the first session_start() call when the cookie is sent to the browser.

For example, this call makes the session valid only for scripts within the current directory:
session_set_cookie_params(0, dirname(__FILE__) . "/");
Here we're using the built-in Php special __FILE__ constant which always gives the absolute path of the file in which it's used.

The Sample Scripts

This simple web project illustrates different possible behaviors for a simple form which tries to remember the form values. The selection value/label entries are generated by the included script:

choices.php
<?php $choices = array( 1=>"AA", "BB", "CC", "DD", "EE", "FF", "GG" );

form1.php

This is a standard reentrant script which holds its values by resetting them based on the incoming query parameters. It has two drawbacks:

form1.php
<? $param = array_merge( $_GET, $_POST ); $sel1 = $param['sel1']; $tf1 = htmlspecialchars($param['tf1']); require_once "choices.php"; $title = basename(__FILE__); ?> <html> <head> <title><?= $title ?></title> <link rel="stylesheet" type="text/css" href="my.css" /> </head> <body> <?php require_once "nav.php"; ?> <h3><?= $title ?>: no session saving, stacking</h3> <blockquote> <? echo "query params: "; print_r($param); ?> </blockquote> <form> tf1: <input type="text" name="tf1" value="<?= $tf1 ?>" /><br /> sel1: <select name="sel1"> <? foreach( $choices as $value => $label ): $isSelected = ($value == $sel1) ? "selected" : ""; ?> <option value="<?= $value ?>" <?= $isSelected ?> ><?= $label ?></option> <? endforeach ?> </select> <br /> <input type="submit" /> </form> </body> </html>
The variations in form2.php and form3.php address these issues.

form2.php

This variation stores parameter values as session values when the parameter is set. This code expresses the idiosyncratic way to do so:
$param = array_merge( $_GET, $_POST );

if (isset($param['tf2'])) {           // if parameter t2 is set
  $_SESSION['tf2'] = $param['tf2'];   //   reset the session value
}

if (isset($param['sel2'])) {
  $_SESSION['sel2'] = $param['sel2'];
}

$sel2 = $_SESSION['sel2'] ;                   // always use values
$tf2 = htmlspecialchars($_SESSION['tf2']);    // taken from the session
We only want to reset the session value only when there is a new paramter value, and after that, always use the session value. By doing so, we can remember the values throughout the session.

form2.php
<? session_start(); $param = array_merge( $_GET, $_POST ); if (isset($param['tf2'])) { $_SESSION['tf2'] = $param['tf2']; } if (isset($param['sel2'])) { $_SESSION['sel2'] = $param['sel2']; } $sel2 = $_SESSION['sel2'] ; $tf2 = htmlspecialchars($_SESSION['tf2']); require_once "choices.php"; $title = basename(__FILE__); ?> <html> <head> <title><?= $title ?></title> <link rel="stylesheet" type="text/css" href="my.css" /> </head> <body> <?php require_once "nav.php"; ?> <h3><?= $title ?>: session saving, stacking</h3> <blockquote> <? echo "query params: "; print_r($param); echo "<br />"; echo '$_SESSION["tf2"] = ', $_SESSION["tf2"]; echo "<br />"; echo '$_SESSION["sel2"] = ', $_SESSION["sel2"]; ?> </blockquote> <form> tf2: <input type="text" name="tf2" value="<?= $tf2 ?>" /><br /> sel2: <select name="sel2"> <? foreach( $choices as $value => $label ): $isSelected = ($value == $sel2) ? "selected" : ""; ?> <option value="<?= $value ?>" <?= $isSelected ?> ><?= $label ?></option> <? endforeach ?> </select> <br /> <input type="submit" /> </form> </body> </html>

form3.php

This variation avoids the stacking of activations which is present in form2.php by calling an external handler script, session-from-query.php whose sole job is to set the session values from the query parameters and redirect back to the original script. Several key features are used in session-from-query.php in order to redirect back to the calling script: Although we could simply write the code as this:
<?php
session_start();
$param = array_merge( $_GET, $_POST );
$_SESSION['tf3'] = $param['tf3'];
$_SESSION['sel3'] = $param['sel3'];
header( "location: form3.php" );
the scheme we've introduced could allow multiple scripts to use this handler. The one down side to this approach is the cost of the extra redirection, a situation which can be improved upon using AJAX. The code is this:

form3.php
<? session_start(); $sel3 = $_SESSION['sel3'] ; $tf3 = htmlspecialchars($_SESSION['tf3']); require_once "choices.php"; $title = basename(__FILE__); ?> <html> <head> <title><?= $title ?></title> <link rel="stylesheet" type="text/css" href="my.css" /> </head> <body> <?php require_once "nav.php"; ?> <h3><?= $title ?>: session saving, no stacking</h3> <blockquote><? echo '$_SESSION["tf3"] = ', $_SESSION["tf3"]; echo "<br />"; echo '$_SESSION["sel3"] = ', $_SESSION["sel3"]; ?></blockquote> <form action="session-from-query.php" > tf3: <input type="text" name="tf3" value="<?= $tf3 ?>" /><br /> sel3: <select name="sel3"> <? foreach( $choices as $value => $label ): $isSelected = ($value == $sel3) ? "selected" : ""; ?> <option value="<?= $value ?>" <?= $isSelected ?> ><?= $label ?></option> <? endforeach ?> </select><br /> <input type="submit" /> </form> </body> </html>

session-from-query.php
<?php session_start(); $param = array_merge( $_GET, $_POST ); // set session values from query parameters foreach ($param as $key => $value) { $_SESSION[$key] = $value; } // Redirect back to script which activated me. // $_SERVER['HTTP_REFERER'] gives the full URL, including the query string. // We need to remove the query string. To do so, use the built-in // parse_url function and obtain the relevant portion. $url = parse_url($_SERVER['HTTP_REFERER']); // $url['path'] is the referer's path only (no query string) // print_r($url); exit(); // use for testing header( "location: " . $url['path'] );


© Robert M. Kline