Logging into an online discussion forum and browsing the threads before posting replies to one, some or all, is an activity that most people just do these days without even thinking about it. Even shopping on a site like Amazon, which remembers your shopping basket as you browse for one last book/movie/gewgaw to purchase and get your order total high enough to achieve the free delivery option without even logging in until it comes time to part with your cash is a non-event these days.
Most people don't stop to think about how this is possible - it just is. You don't ask the shopping basket in your local supermarket how it remembers if there are carrots and peas in there already before you pickup the potatoes, so why is the internet shopping basket any different?
Creation - Destruction - Creation
What most people do not realise is that the internet has no memory!
Well, okay. There are search engines which store copies of web pages from times gone past, and if you have already visited this site and commented it will still be there the next time you come along.
What I mean is that the underpinning protocol of the internet, the HyperText Transfer Protocol (HTTP), has no inherent ability to remember things. It is what is called a stateless protocol, which means that once a new request is made (by clicking a link or posting a form), the new page doesn't know what was happening on the last one. This is because of the architecture used in connecting your computer by cable to a server in some unknown location and getting a web page from there to you.
Now, you and I know that this is not what seems to be really happening - your logins are remembered on the message boards, and your prospective purchases are remembered in the shopping basket.
Read on to find out how:
Some clever people came up with a method of passing information, such as user login, from one page to another in the early days of the internet.
The way it worked is that when the browser requests a page from a website, the server checks to see if a session ID is being sent with the request. If there is no session ID, then the server will generate a random one (the random bit is important later), and send the new session ID with the rest of the page. At this point, the server has also created a session file (or a database record) associated with that ID to act as a datastore for information which might be needed. A timer is usually set as well, so that the session is only valid for a limited time (which is why, sometimes, when you spend 30 minutes agonising over whether to get the new Super-Scary-Epic Movie and then click 'buy', your shopping basket empties out).
The next time the user clicks on a link, the session ID is also sent, and the server checks to see if there is a valid file (or record) that matches, and makes the information in the file available to whatever scripts are being used to generate the new page. The timer is reset, so you get another 30 minutes to agonise over getting the sequel.
The session ID is usually stored as a cookie on the client. In fact, cookies can store the same information that might be stored in the session file on the server. However, there are issues of security and performance (all cookie information for a particular site is sent back and forth every time a page is requested) - so it is a good idea to store as little as possible in cookies. I won't be talking much about cookies for the rest of this article, but I will come back to them some other day. For now, the only cookie that matters is the one that stores our session ID, and we don't really have a lot more to say about it.
The last thing about the session cookie on the client is that it will "stay alive" until the browser is closed. This means that if you go to a completely different site, and then return to the shop a little later (before the session timeout), your selected items will still be there. This is also why you can easily recover sessions if your Firefox crashes on you (I don't regularly use IE, but I expect version 7 is likely the same).
If cookies are blocked by a client, for whatever reason, then the resort is to put the session ID in the URL. For example, a site might have its links looking like http://www.example.com/page.php?PHP_SESS_ID=a1fbfbf120c02 or somesuch. Most servers are configured to do this transparently these days and, besides, blocked cookies are becoming less and less common these days, so it isn't really a problem.
So, a session is the time over which a user is interacting with your site, and the session data is the information collected and stored over that time
Now, that's all fair enough, but what can you do with it?
If you're using a server-side script to generate pages, then quite a bit. You can take information from a posted form, or in the query string, and add it to the session data. You can then retrieve this information and redisplay it , or save it in the database. You can remove information from the session data, and modify it. And you can do this freely within your scripts.
By default, PHP stores session data in files, although it can make us of databases and there are a number of functions that can be used to enhance session handling in scripts. For beginners, though, the default handling is usually enough.
In PHP, there is one initial requirement for using sessions. Every page must call the session_start() function before any information is sent to the client from the server, and before you can actually access the session data.
After that is done, the session data is accessed with the $_SESSION superglobal array.
Typically, I make sure that one of the first things that happen in my PHP scripts is the inclusion of a common file which does all of the things that must happen before the page can be created.
So, in the file "index.php", for example, I would have something like:
<?php // index.php require_once('/includes/common.php'); // page code goes below here ?>
And then in my common file, I would have:
<?php // includes/common.php session_start(); // other necessary things for startup here... ?>
There are actually a lot of settings in the PHP configuration itself which affect session behaviour - but the out-of-the-box settings are typically enough for most uses. There will be a more detailed article on PHP configuration at a later date.
This is about the simplest example of using sessions:
<?php // index.php require_once('/includes/common.php'); // page code goes below here $page_output = ''; if (isset($_GET['forgetme'])) { if (isset($_SESSION['username'])) { unset($_SESSION['username']); } } if (isset($_POST['username'])) { $_SESSION['username'] = $_POST['username']; } if (isset($_SESSION['username'])) { $page_output .= '<p>Hello ' . htmlentities($_SESSION['username']) . '!</p>'; if (isset($_GET['remember'])) { $page_output .= '<p>See, I told you I would remember you</p>'; } $page_output .= '<p>Click <a href="index.php?remember=true">here</a> and I will remember who you are</p>'; $page_output .= '<p>Click <a href="index.php?forgetme=true">here</a> and I will forget you</p>'; } else { $page_output .= '<form action="index.php" method="post">'; $page_output .= '<label for="fm_username">Enter Username</label>:'; $page_output .= '<input type="text" id="fm_username" name="username" />'; $page_output .= '<input type="submit" value="submit" />'; $page_output .= '</form>'; } echo $page_output; ?>
So, we access the session variables as part of the $_SESSION superglobal. The example also uses $_GET and $_POST in various guises in order to control the actual session data.
When a user opens the page for the first time, they are presented with the form:
$page_output .= '<form action="index.php" method="post">'; $page_output .= '<label for="fm_username">Enter Username</label>:'; $page_output .= '<input type="text" id="fm_username" name="username" />'; $page_output .= '<input type="submit" value="submit" />'; $page_output .= '</form>';
This is because the check for the session value we are interested in (namely the username) has turned up false:
if (isset($_SESSION['username'])) {
Then, when the form is submitted, the script picks up the username and writes it to the session:
if (isset($_POST['username'])) { $_SESSION['username'] = $_POST['username']; }
Now, everytime the user loads the page with the "remember" link, the script pulls the information back out again:
if (isset($_SESSION['username'])) { $page_output .= '<p>Hello ' . htmlentities($_SESSION['username']) . '!</p>'; if (isset($_GET['remember'])) { $page_output .= '<p>See, I told you I would remember you</p>'; } $page_output .= '<p>Click <a href="index.php?remember=true">here</a> and I will remember who you are</p>'; $page_output .= '<p>Click <a href="index.php?forgetme=true">here</a> and I will forget you</p>'; }
This would be available even if the user now opened another page on the same site (you don't even need the remember parameter) - so long as you call session_start() at the top of the script (which you will be doing if you always include the common.php file).
Finally, we manually destroy the username when the user clicks to forget:
if (isset($_GET['forgetme'])) { if (isset($_SESSION['username'])) { unset($_SESSION['username']); } }
Of course, the session is killed by the server after a time limit (24 minutes is the default), too.