A quick tutorial on sessions in php
I find I get a lot of questions about sessions in php. There is nothing at all that is complex about sessions, and it’s a mystery to me why they are somewhat mystical to others!
So here’s a very brief tutorial on them.
Introduction
The Web is a stateless environment. Every interaction between a user and a webserver is a single instance. There is no way to “pause” a script to wait for user input and then continue. Conversely, for just about any form of user interactive web-site application it is absolutely vital to be able to “pause ” the script and mimic a “stateful” architecture. We do this with sessions.
In this tutorial we will look at the following:
- How to start a session
- What PHP actually does when you start a session
- How to stop a session
- Using Session Data
- Different types of session handling
- Session expiry
How to start sessions
In just about every application that uses sessions you would want to start the session at the very first line of the page. Starting a session is as simple as typing:
session_start(); |
What PHP actually does when you start a session
There are a whole bunch of things that PHP does for you when you call “session_start()”. In order these are
-
Identification of the Session ID
-
Retrieval of Session Data
-
Session Garbage Collection
PHP first checks to see whether it has received a cookie called (by default) PHPSESSID (you can change this in php.ini under the setting session.name).
If PHP can’t find the cookie it then looks in the $_GET and $_POST variables for the same variable provided the php.ini directive session_use_only_cookies is not set to “1″ (which is the default). (More on this in url_rewriting)
If it can’t find a cookie (or a variable) then it creates a new session id and sends a cookie to the browser.
If it does find a cookie then php looks in the session store (typically a file in the filesystem but it could be a database – see below on using a database as a session store) and reads the contents of the file called sess_[sessionid].
It then unserialises the string that is in the file (if there is one) and uses the unserialised values to create the variables in the $_SESSION array.
This is what PHP calls the purging of old sessions. There is an internal algorithm that you can influence that decides whether the garbage collection will be performed. If it is to be performed then PHP has a look at all the current sessions and deletes those that are older than a certain time period (specified in php.ini under session.gc_maxlifetime).
From the above you can see that you can’t address session data until you have “started” the session. You need php to have identified the session id, found the file in the filesystem and unserialised the data in it before you can do so.
Note that above I say that the call to session_start() must be the first line of a page. This is not strictly true, but the call must be before any other output is sent to the browser, if you are using cookie based sessions. This is because cookie information is delivered to the browser in the header and headers are automatically closed once any real output is sent.
How to stop a session
A session is stopped and the data is saved when the script ends. You don’t need to do anything.
Sometimes you get what is called a ‘race condition’. This can occur when a session is opened in a new script before the old session is fully written and saved to the file. With modern systems, and the speed of file i/o functions, this is unlikely to be a problem unless you are working on a localhost. To get around this problem, if you are suffering, just add this at the end of your scripts
session_write_close(); |
To eradicate a session completely (for example in a logoff script) you take the following steps:
- remove the session data
- destroy the client side cookie and thus the session id; and
- destroy the server side stored data
You do this as follows
<?php session_start(); $_SESSION = array() ; //zero all the active session data //now flush the cookie if (isset($_COOKIE[session_name()])){ setcookie(session_name(), '', time() - 42000, '/'); // set a new cookie with no data that auto-expires } session_destroy() ; //finish the job ?> |
But remember there are times when you don’t want to kill a session completely but just want to stop a user or a script from having access to certain data. For this you need to address individual elements of the $_SESSION variable. For example
if (isset($_SESSION['someelement'])){ unset ($_SESSION['someelement']); } |
Using Session Data
As set out above, session data is stored in the $_SESSION variable. $_SESSION is a superglobal which means it can be addressed everywhere in your code, in functions, in objects and in scripts. But, you must have started the session before the variable exists. If the reason for this is not obvious go back to the start of the tutorial and re-read the bit about what actually happens when you start a session.
To store data in a session you assign it to the superglobal just as you would use any array:
<?php session_start(); //let's assume you have provided a way for a // user to be identified by name if (isset($_POST['username'])){ $username= $_POST['username']; } else { $username="Anonymous"; } //now store the username in a session variable $_SESSION['username'] = $username; ?> |
it is as simple as that. then on every subsequent visit to the webserver your scripts can identify the user by the following script:
<?php session_start(); echo "Welcome back $_SESSION[username]"; ?> |
The flaw in the above code is that the garbage collection may have got rid of the session data in the interim. It is therefore better practice to write a little library function that might look something like this and “include” it at the top of every page, just under the call to session_start.
<?php if (!isset($_SESSION['username'])){ if (!isset($_POST['username'])){ $_SESSION['username'] = 'Anonymous'; } else { $_SESSION['username'] = $_POST['username']; } } echo "Welcome back $_SESSION[username]"; ?> |
Different types of session handling
There are good reasons for wanting to change your session handling system. One is security – php installations on shared hosts tend to store all session data in the same directory; another is if you want the session data to be able to be persistent permanently (for example if you are writing a questionnaire and you want to let people come back a week later to finish it). You can achieve persistence of data by storing the session data in a database against, say, a client login.
I will post a solution for database session management another time.