PHPRO.ORG

Introduction To PHP Sessions

Introduction To PHP Sessions

by Kevin Waterson

Contents

  1. What is a session?
  2. How do I use a Session?
  3. How do sessions work?
  4. How do I change the value of a session variable?
  5. Can I destroy a session variable?
  6. What should I do to destroy a whole session?
  7. Can I store an array in a session?
  8. Can I store an object in a session?
  9. Can I store an file pointer in a session?
  10. Can I store a function in a session?
  11. Can I store an image in a session?
  12. How are sessions stored?
  13. Storing sessions with SQLite
  14. When do sessions expire?
  15. How can I send headers then start a session?
  16. How can I check if a session is started?
  17. How can I check if a session uses a cookie or query string
  18. Session Configuration with php.ini
  19. Session security

What is a session?

A session is basically a way of storing variables and making them available across multiple pages on your web site. This can be very useful as the user does not ever need to see what is going on behind the scenes. Nor do we need to fill the URL with mind boggling long strings like
http://example.com/file.php?id=6&item=pet&type=cat&color=black&eyes=1&temperament=aloof&var=etc
Also the need for the user to post a form is not required, so all interaction is hidden from the user.

How do I use a session?

Here we will demonstrate a session in its simplest form, that is, setting a session variable on a web page and recalling the value of it on a second page. We will begin by creating a session variable called 'foo' and we shall assign the value of 'bar' to it. A session variable looks like this..
$_SESSION['variable']
We use the PHP super global $_SESSION to hold it. More on this later. Our first page we will call page1.php and the code will look like this...

<?php
// begin the session
session_start(); 

// set the value of the session variable 'foo'
$_SESSION['foo']='bar'

// echo a little message to say it is done
echo 'Setting value of foo'
?>

With that done, we can create page2.php, this page will start a session, then it will echo the value of the session variable 'foo'. The code for page2.php will look like this..


<?php 
// begin our session
session_start(); 

// echo the session variable
echo 'The value of foo is '.$_SESSION['foo']; 
?>

Try the above example, we will build on it as we go and discover new things to do with sessions, but first, lets look at what happened here. On page2.php we again used session_start(). You must use this on every page you wish to use sessions. In most cases, it will be the first line of code on the page that does anything, following <?php. This tells PHP that a session is happening and to load up the session variables, if a session is not already active, PHP will begin a new session upon adding a new variable to $_SESSION.
You cannot send ANYTHING to the browser before session_start()
This means no text, not even a newline or a space. There an method of doing this but more of that later. Lets change our page2.php to echo some text before we use session_start()


<?php

// output some text to the browser before starting the session
echo 'This is a bad thing to do';

// begin our session
session_start();
                                                                                                                       
// echo the session variable
echo 'The value of foo is '.$_SESSION['foo'];
?>

When you access page2.php with the above code, it will give you an error that looks something like this..
This is a bad thing to do
Warning: session_start() [function.session-start]: Cannot send session cookie - headers already sent by (output started at /html/page2.php:4) in /html/page2.php on line 7

Warning: session_start() [function.session-start]: Cannot send session cache limiter - headers already sent (output started at /html/page2.php:4) in /html/page2.php on line 7
The value of foo is

As you can see, when the script reaches the session_start() on line 7, it gives an error. This is because session_start() sends headers to the browser, as does sending text. These headers may only be sent once.

How do sessions work?

Sessions can be used in two ways. The first is cookie based, and the second is url based.
Most sessions are cookie based. What this means is that when a session is started, a cookie is set on the clients machine with a unique session ID or SID. The session variables are stored typically on a file on the server that matches the unique session ID. When a variable is required, the client or browser looks for the file matching the session ID and retrieves the corresponding variables from it. A typical session file stored in the default session file directory would look like this
sess_fd51ab4d1820aa6ea27a01d439fe9959
Using our example session from above, this file would contain our session information in an array. An array of 1 is a little lacking for our purposes so lets create several session variables. To demonstrate this lets make a new page1.php with the following code...

<?php
// begin the session
session_start();
                                                                                                                       
// set the value of the session variable 'foo'
$_SESSION['foo']='bar';
                                                                                                                       
// set the value of the session variable 'bar'
$_SESSION['bar']='foo';
                                                                                                                       
// set the value of the session variable 'foobar'
$_SESSION['foobar']='fubar';
                                                                                                                       
// echo a little message to say it is done
echo 'Setting session values';
?>

With this, the session variables foo, bar, and foobar have been stored in the $_SESSION array.
To access them we use the global variable $_SESSION and the array key of the variable we require. To view all the session variables, we can use the following code in our page2.php file

<?php
// begin the session
session_start();

// loop through the session array with foreach
foreach($_SESSION as $key=>$value)
    {
    
// and print out the values
    
echo 'The value of $_SESSION['."'".$key."'".'] is '."'".$value."'".' <br />';
    }
?>

The output of page2.php should look like this...
The value of $_SESSION['foo'] is 'bar'
The value of $_SESSION['bar'] is 'foo'
The value of $_SESSION['foobar'] is 'fubar'

As you can see above, when we loop throught the $_SESSION array, the value are displayed. The actual file that stores the session looks like this...
|s:3:"bar";bar|s:3:"foo";foobar|s:5:"fubar";

How do I change the value of a session variable

This is easily achieved by simply declaring the variable again like so..
If page1.php set the value of $_SESSION['foo']='bar'; the value can be changed by resetting it like
$_SESSION['foo']='newbar';
It really is that simple.

Can I destroy a session variable?

Of course. Here we can use the php function unset()
unset($_SESSION['foo']);
Do not do something like unset($_SESSION) as this will stuff up everything and you will not be able to register variables via $_SESSION.

What should I do to destroy a whole session?

This is often used to log out of applications that store the login information in a session. You can use the code below to destroy your session completely.

<?php
// Begin the session
session_start();
                                                                                                                       
// Unset all of the session variables.
session_unset();

// Destroy the session.
session_destroy();
?>

Can I store an array in a session?

Sure, this is simply done in the same way as setting regular variables.
Lets create a new page1.php with the following code..

<?php
// begin the session
session_start();
                                                                                                                       
// create an array
$my_array=array('cat''dog''mouse''bird''crocodile''wombat''koala''kangaroo');

// put the array in a session variable
$_SESSION['animals']=$my_array;

// a little message to say we have done it
echo 'Putting array into a session variable';
?>

Now that we have the array $my_array in a session variable called $_SESSION['animals'] we can have a look through the array as we choose. Use this snippet to create a new page2.php file

<?php
// begin the session
session_start();
                                                                                                                       
// loop through the session array with foreach
foreach($_SESSION['animals'] as $key=>$value)
    {
    
// and print out the values
    
echo 'The value of $_SESSION['."'".$key."'".'] is '."'".$value."'".' <br />';
    }
?>

The result of the above code will show you the session array, with the array keys
The value of $_SESSION['0'] is 'cat'
The value of $_SESSION['1'] is 'dog'
The value of $_SESSION['2'] is 'mouse'
The value of $_SESSION['3'] is 'bird'
The value of $_SESSION['4'] is 'crocodile'
The value of $_SESSION['5'] is 'wombat'
The value of $_SESSION['6'] is 'koala'
The value of $_SESSION['7'] is 'kangaroo'

You could of course, simply choose individual array members if your page2.php file looked like this..

<?php
// begin the session
session_start();

// echo a single member of the array
echo $_SESSION['animals'][3];
?>

This would simply retrieve the value for the 4th member of the array and print 'bird'.

Can I store an object in a session

Yes, using the following code we can include our class file as we would for any class. In page1.php we will instantiate a new object and put it in a session variable. Lets us create a simple class file to include in our page1 and page2 scripts, we shall call it myclass.php

<?php
// our class
class mySessionClass{
                                                                                                                       
// The constructor, duh!
function __construct(){
}
                                                                                                                       
// a function to set a property
function bar(){
  return 
'foo';
}
                                                                                                                       
// end of class
?>

In page1.php we include the class file and instantiate a new instance of the class directly into a session variable.

<?php
// include the class file
include('myclass.php');

// begin the session
session_start();

// instantiate a new instance of the class mySessionClass
$_SESSION['foo']= new mySessionClass
                                                                                                                       
// echo a little message to say it is done
echo 'Setting value of foo to an object';
?>

Now we have the object in a session variable, we can go on to page2.php and use methods from mySessionClass.

<?php

// include the class file
include('myclass.php');

// begin the session
session_start();
                                                                                                                       
echo 
$_SESSION['foo']->bar();
?>
Important Note: You MUST include the class definition on *every page* when you store an object

Can I store a file pointer in a session

The short answer is NO. Lets create a page1.php and page2.php and see what happens. Page1.php will look like this:

<?php

  
// make it or break it
  
session_start();

  
// create a file pointer
  
$fp fopen('my_file.txt'"r");

  
// set the file pointer to a session variable
  
$_SESSION['filePointer'] = $fp
?>

<a href="page2.php">link to page 2</a>

?>

Everything here is fine. the variable is set and no error should be seen. page2.php should look like this:

<?php
  
// make it or break it
  
error_reporting(E_ALL);

  
// begin our session
  
session_start();

  
// try to the read from the file pointer
  
$contents fread ($_SESSION['filePointer'], filesize ($filename));

  
// close the file
  
fclose ($_SESSION['filePointer']);

  
// echo the files contents
  
echo "Contents: $contents"

?>

The above code will produce an error similar to this
Notice: Undefined variable: filename in /html/page2.php on line 10

Warning: fread(): supplied argument is not a valid stream resource in /html/page2.php on line 10

Warning: fclose(): supplied argument is not a valid stream resource in /html/page2.php on line 13

Contents:

As you can see, no success on storing the file pointer.

Can I store a function in a session?

Are you crazy? Why oh why would you be doing this??
Well, yes you can. There are some limitations, it is fraught with danger, and is a major pain to debug, but yes, it can be done. Lets take begin with making a page1.php script to set a session variable with a function in there.


<?php

// begin our session
session_start();

// set a session variable containing a function
$_SESSION['foo'] = '
<?php 
function foo(){
echo "I am stored in a session function named foo";}
?>'
;

?>
<a href="page2.php">page 2</a>

Ok, lets now create page2.php and see what results we can get


<?php

  
// begin our session
  
session_start();

  
// evaluate the code within the session variable
  
eval('?>'.$_SESSION['foo']);

 
// run our stored function
 
foo();

?>

The above page2.php will echo
I am stored in a session function named foo
just the way it is declared. This is fun, but what if we want to feed the function a paramater, say an array, and have it give us the values. Lets recreate page1.php so it looks like this:


<?php

session_start
();

$_SESSION['arrToString']='
<?php
/**
*
* Function arrToString
* Convert array to string using key value
*
* @param array $array
*
* @return void
*/
function arrToString($array){
 // our string variable
 $string="";
 // loop over our array
 foreach($array as $k=>$v)
        {
        // add key and value to the string
        $string .= $k."-".$v."<br />";
        }
  // echo our string
  echo $string;
}
?>'
;
?>

<a href="page2.php">Page 2</a>

As you can see we have this time used a function that contains a little logic and loops over and array and echoes the string of the keys and values. Ok, its not rocket science, but a useful example. In page2.php will with create an array of animals and use the arrToString() function that is stored in the session to show the values of the array.


<?php

  
// start our session
  
session_start();

  
// create an array of animals
  
$array = array('dingo''wombat''perl''kangaroo');

  
// evaluate the function stored within the session variable
  
eval('?>'.$_SESSION['arrToString']);

  
// execute the funtion, passing the array as an arg
  
arrToString($array);
?>

The above code will produce a string like
0-dingo
1-wombat
2-perl
3-kangaroo
As it echoes out the key-value pairs of the array. Again, this method is pinholed with problems and we really on show it here in the "because you can" category and to show some of the possibilities of sessions. Don't try this at home kids.

Can I store an image in a session?

Once again, this is not something you would normally do, but, is most surely doable. Storing small images in a session may be useful for use instead of text emails addresses on your pages or a variety of other reasons. It is not recommended to store larger images due to memory constraints. But lets see how we go with storing a simple image in the database. Again, we start with page1.php to start our session and stick an image in there.


<?php

// make it or break it
error_reporting(E_ALL);

// begin our session
session_start();

// specify an image
$image './pr0n.jpg';

// check the file exists on the file system
if(file_exists($image))
    {
    
// stuff the image info into a session 
    
$_SESSION['image']['info'] = getImageSize($image);
    
// stuff the image into a session var
    
$_SESSION['image']['imagedata'] = file_get_contents($image);
    echo 
'Image '.$image.' is now in a session variable.<br />';
    }
else
    {
    
// if we fail to find the image file
    
echo '<div>Failed to find file ' $image '</div>';
    }
?>
<a href="page2.php">Page 2</a>

Ok, so now we have our image in a session, we need to be able to show it. This is the basically the same as displaying images from the filesystem or a database in that we set the correct headers, and echo the image string.


<?php
ob_start
();

session_start();

        
// set the header for the image
        
header("Content-type: image/jpeg");
echo 
$_SESSION['image']['imagedata'];

ob_end_flush();
?>

Here we have used ob_start() as we have started our session which sends headers, then we have again sent headers with jpeg headers. Output buffering allows us to escape the dreaded "Headers already sent on line...." type errors. Once again, this is not a recommended use of sessions, but again gives an insite into what the can potentially be used for.

How are sessions stored?

The default behaviour for session storage is to save the session data in a file. This behaviour can be altered by changing the session.save_handler in your php.ini file. Options can be:

As we saw earlier the format of saving session data in files looks like this..
|s:3:"bar";bar|s:3:"foo";foobar|s:5:"fubar";
If we choose we can have this stored in one of the options above. The mm option saves the session data into memory, this also gives significant speed increase and is often recommended by tutorials for fine tuning PHP and apache web server. Sessions may also be stored in a database. This option provides for greater manageability of sessions and allows the programmer to perform tasks such as counting of active sessions etc. With the advent of PHP5, we now have SQLite bundled with PHP. If PHP is configured --with-sqlite, you will have access to saving sessions with a PHP native database, although SQLite is not truly a database, but a file abstraction layer with and SQL interface.

Storing sessions with SQLite

As mentioned above, one of the methods given for sessions storage is SQLite. To do this you need access to the php.ini file and change the line:
session.save_handler = files
to read
session.save_handler = sqlite
You will also need to set the file in which the sessions database is to be stored. To do this you need to uncomment and edit the line
;session.save_path = "/tmp
to read
session.save_path = "/tmp/session.sdb"
Where sessions.sdb is the name of the SQLite database file. You could call it Wilma.ext if you wanted, or anything you like. You can even create your own directory and put it there instead of /tmp. If the session.sdb file does not exist, it will be created when session_start() is called. The database that is created a contains a single table named session_data which itself contains three fields:

  • sess_id
  • value
  • updated

This is very useful for us for session management when we need to do things like time out sessions etc. The sess_id field contains a sessions ID (duh) and has a value of a normal session file eg:
31205c15acf956733507b54889ec9b83
The value field contains a serialized array of session variable names and thier values.
The updated field contains a unix timestamp and records the EPOCH time of the session creation or the last update to that session.

If you are unfamiliar with SQLite you are encouraged to read the Introduction to SQLite tutorials. Here we borrow from that tutorial the section on Session Management

There has been much debate over the use of SQLite as a tool of session management, and it would seem that the outcome has some bonuses and some failings. Some of the those opposed to session management have failed to realise that some of the alleged disadvantages of using SQLite are its greatest assets. Lets look at the two biggest hurdles that have aggrieved some users.

  • Single file for entire database:
  • No practical advantage

It has been put by some that SQLite is not intended for a write intensive environment as it uses a single file for the database. This could pose problems when updating sessions. Every time a session is updated the database file is locked and so that multiple sessions must be updated one at a time rather than together. Another problem could be corruption. Should a single SQLite based session be corrupted, all sessions will be lost. Having a single point of access implicitly decrees a single point of failure and a single point of performance degredation.

We see the single file database a major feature of SQLite. It provides the same benifits as myisam datafiles in this respect, while at the same time offering a clean and manageable code by allowing us to identify and destroy a session out of band. While the single point of failure arguement does hold water it has little meaning in this context as the mm session handler is itself a single point of failure. Single file management also has benifits with regard to maintainence, it is much easier to delete a single file rather than many session files in /tmp, also, finding and manipulation of data outside normal sessions framework becomes much easier, as does moving sessions across servers.

Benchmarks I have seen regarding session management do show a decrease in performance under high loads, but under low loads this seems of little consequence. As a SQLite based session write is only a small part of a script, the performance penalty does not propogate linearly but remains a constant, thus longer running scripts will not incur an exponetial slowdown. It is correct that enterprise type sites would not benifit from the use of SQLite based sessions but, enterprise sites would most likely not be using SQLite.

When do sessions expire?

The default behaviour for sessions is to keep a session open indefinitely and only to expire a session when the browser is closed. This behaviour can be changed in the php.ini file by altering the line
session.cookie_lifetime = 0
to a value in seconds. If you wanted the session to finish in 5 minutes you would set this to
session.cookie_lifetime = 300
and restart your httpd server.
The session lifetime may also be altered at from the calling script using session_set_cookie_params(), however this has limitted use as the params last only for the duration of the script. This function must be called _before_ session_start() on every request.

How can I send headers then start a session?

Earlier we mentioned that you cannot send anything to the browser before session_start(). This is because when you set a header, you cannot do it twice. When you send text to the browser, headers are sent also. However, PHP does provide a method to set headers, send text, and still be able to start your session. The ob_start() function allows you to buffer your output till you are ready to send content to the browser.

<?php

  
// make it or break it
  
error_reporting(E_ALL);

  
// begin output buffering
  
ob_start();

  
// send a header
  
header ("Pragma: no-cache");

  
// send some text to the browser
  
echo 'This is a line of text';

  
// then we start our session 
  
session_start();

  
// set the value of the session variable 'foo'
  
$_SESSION['foo']='bar';

  
// flush the buffer
  
ob_end_flush();

?>

Run this snippet of code and it will output the text
This is a line of text
First we sent a header with the no-cache, then echoed some text and finally started a session and set a session variable.

How can I check if a session is started

Many times when including files you may not know if a session already is started. To check for the existance of a session you can simply check for the Session ID (SID). SID is a constant that is set when the session is started. We need only check to see if the SID constant is defined. This little snippet shows how.

<?php

if (defined('SID'))
        {
        echo 
'Session is active';
        }
else
        {
        echo 
'Session is not started';
        }

?>

If you have used the above code without alteration it will echo the line
Session is not started
because nowhere in the code does session_start() exist. If you begin with session_start() or include this snippet in another php that has session_start() then it will echo the line
Session is active

How can I check if a session uses a cookie or query string

When a session is started, the Session ID is, by default, stored in a cookie on the clients machine. But if the clients web browsers does not support cookies, or has cookies turned off, then PHP will try to send the Session ID via the query string. This will give a url like:
http://www.example.com/file.php?SID=43b4a19d1962304012a7531fb2bc50dd

This is generally considered bad practice due to security concerns, and transparent session id support is disable by default in php.ini. If you have this enabled, you can check if the client is using cookies or the query string like this:

<?php
/*** begin a session ***/
session_start();

if(isset(
$_COOKIE['PHPSESSID']))
        {
        echo 
'The session ID has been store in a cookie';
        }
if (
defined(SID))
        {
        echo 
'The session ID has been stored in the query string';
        }
?>

Session Configuration with php.ini

The behaviour of PHP Sessions is controlled by configurations options in the php.ini file. These cover a wide range of behaviour and can be set only by users who have write access to php.ini, usually the super-user or root. These options are described here.

Session security

This has a been an often debated point against the use of sessions. The reality is that a session, like any other programming method, will be as secure as you make it. With the advent of session came new ways in which a malicious user could hijack your session and your identity.

It is beyond the scope of this introduction to go in-depth into session security and is left as an exercise to the reader to hunt out resources for session security. An excellent place to begin is of course The php manual.