by Kevin Waterson
Contents
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();
?>
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.
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:
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.
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 myiam 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.
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 this fine article on Securing Sessions , and of course there is always, The php manual.