PHP Sessions
Sessions are designed to exist within a current user session. They also run purely on the server side and unlike Cookies nothing is pushed to the browser’s cache (client side).
So, what are sessions good for?
Imagine you have a shopping cart site that requires a login and password to a user’s account. This site has two parts to it: a section that requires no authorisation and a section that needs you to be logged in to see or interact with the information.
Now, consider a situation where somebody needed to gain access to the authorised section of your site – they will need a username and password to login. Once logged in it would be helpful to store a flag that demonstrates they are logged in and can see those pages. You may also wish to store their password and compare that with the DB on every page load to make sure that the login data belongs to the user that originally logged in.
You could store a PHP flag on that page that signifies the login was successful but if the user goes to another section of your site that requires authorisation you have lost that flag. So what to do? This is what sessions are designed for. I use the term with care but they could be referred to as a global array which stores variables and arrays that can be accessed whenever needed by the logged in user no matter where they are within the site.
With that in mind we could store our PHP flag in a session variable that can be accessed whenever the logged in user clicks through the application – each time the Session variable is checked to make sure the user is still logged in. When the user logs out we then set the flag to say FALSE to signify that the user has now logged out, empty any variables and if necessary kill the session.
Shopping carts are also made for sessions – similar to our logged in example above we can use sessions to store the progress of an order as the user progresses through the site selecting items as they go. We can then access those variables to calculate the sub-total, gross amount and shipping. Once the order has been completed we can then write that data to a database as a completed order.
What is the difference between Sessions and Cookies?
- Sessions only exist for as long as the user is using the site
- Sessions are server based and nothing is pushed to the client unlike cookies that exist within the browser’s cache
- Sessions can store more data than a cookie
Practical example
We will build a simple app based on an imaginary bookstore. We will create three files: some controller code (index.php) and two views, books.php which will store the books available and basket.php which will store the products that the user has chosen.
Controller Code
$items = array( array('id' => '1', 'desc' => 'Complete Works of Shakespeare', 'price' => 24.95), array('id' => '2', 'desc' => 'Experimental Drawing Techniques', 'price' => 11.99), array('id' => '3', 'desc' => 'Life of Brian Audio Book', 'price' => 19.99), array('id' => '4', 'desc' => 'Chess Player\'s Bible', 'price' => 14.95)); session_start(); if (!isset($_SESSION['basket'])) { $_SESSION['basket'] = array(); } if (isset($_POST['action']) and $_POST['action'] == 'Buy') { // Add item to the end of the $_SESSION['basket'] array $_SESSION['basket'][] = $_POST['id']; header('Location: .'); exit(); } if (isset($_POST['action']) and $_POST['action'] == 'Empty basket') { // Empty the $_SESSION['basket'] array unset($_SESSION['basket']); header('Location: ?basket'); exit(); } if (isset($_GET['basket'])) { $basket = array(); $total = 0; foreach ($_SESSION['basket'] as $id) { foreach ($items as $product) { if ($product['id'] == $id) { $basket[] = $product; $total += $product['price']; break; } } } include 'basket.php'; exit(); } include 'books.php';
What’s happening?
We have an array and two event listeners. The array is a two dimensional array (in normal cases this data would be retrieved from a database). The first event listener is the Buy event listener – when the but button is clicked the product is retrieved and added to the session array.
The other event empties the basket and ends the session. The final event retrieves the contents of the basket and displays the status of the basket in the event the user needs to view what they have bought at any time.
Notice also the use of sesson_start(). This will be called every time we start or end a session.
View code (books.php)
<body> <p>Your shopping basket contains <?php echo count($_SESSION['basket']); ?> items.</p> <p><a href="?cart">View your basket</a></p> <table border="1"> <thead> <tr> <th>Item Description</th> <th>Price</th> </tr> </thead> <tbody> <?php foreach ($items as $item): ?> <tr> <td><?php htmlout($item['desc']); ?></td> <td> £<?php echo number_format($item['price'], 2); ?> </td> <td> <form action="" method="post"> <div> <input type="hidden" name="id" value="<?php htmlout($item['id']); ?>"/> <input type="submit" name="action" value="Buy"/> </div> </form> </td> </tr> <?php endforeach; ?> </tbody> </table> <p>All prices are in pounds sterling.</p> </body>
What’s happening?
In the books view we are displaying what’s available to buy. There is a click handler that links back to the buy event listener in the index controller code.
View (basket.php)
<body> <h1>Your Shopping Cart</h1> <?php if (count($cart) > 0): ?> <table> <thead> <tr> <th>Item Description</th> <th>Price</th> </tr> </thead> <tfoot> <tr> <td>Total:</td> <td>£<?php echo number_format($total, 2); ?></td> </tr> </tfoot> <tbody> <?php foreach ($cart as $item): ?> <tr> <td><?php htmlout($item['desc']); ?></td> <td> £<?php echo number_format($item['price'], 2); ?> </td> </tr> <?php endforeach; ?> </tbody> </table> <?php else: ?> <p>Your cart is empty!</p> <?php endif; ?> <form action="?" method="post"> <p> <a href="?">Continue shopping</a> or <input type="submit" name="action" value="Empty cart"/> </p> </form> </body>
What’s happening?
In the basket view we are displaying the status of the user’s basket.. There is a click handler that links back to the empty basket event listener in the index controller code which empties the entire basket. We could do more with this such as allowing users remove specific items.
In summary
We have explored the difference between sessions and cookies. We have also analysed some classic use cases for sessions and built a simple shopping basket app to demonstrate how sessions work. A word of caution on sessions: try not depend on them too much. They can lead to lazy coding where a better alternative would be to call data within functions. Only use them where it is essential that data needs to be accessed from memory by different aspects of your application.
Be careful of overhead as well – keep data in sessions specific with as few bytes or elements as possible (store only what you need!).
A word of caution on sessions: try not depend on them too much. They can lead to lazy coding where a better alternative would be to call data within functions.