Goals
We'll see how you use variables to track data about users.
Notes
You may have heard of the hot new band, Evil Squirrels. Here they are:


Let's make an application that lets people order Evil Squirrels t-shirts. Buyers will be able to select a t-shirt, and enter the quantity they want. They'll have a shopping cart to track the number of each shirt they have ordered. We'll use session variables to track everything.
Your first task is to try the site. Look at every page. Enter orders. Have a look at the shopping cart. Obviously, the cart isn't that great, but it will do for our purposes.
Now download the site's zip file and extract it somewhere. Have it on hand so you can mess with it.
Templating
Before we get into the shopping cart, let's look at the templating used on the site. Compare the source code of any of the pages. Here's the start of one of them:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<title>Evil Squirrels T-Shirts: Welcome</title>
<link type="text/css" rel="stylesheet" href="lib/screen.css">
</head>
<body>
<div id="header">
<h1>Evil Squirrels T-Shirts</h1>
<h2>Welcome</h2>
</div>
<div id="menu">
<ul>
<li><a href="./">Home</a></li>
</ul>
Here's the start of another:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<title>Evil Squirrels T-Shirts: Mapa</title>
<link type="text/css" rel="stylesheet" href="lib/screen.css">
</head>
<body>
<div id="header">
<h1>Evil Squirrels T-Shirts</h1>
<h2>Mapa</h2>
</div>
<div id="menu">
<ul>
<li><a href="./">Home</a></li>
</ul>
They're very similar to each other. In fact, every page has the same structure:

Obviously, we wouldn't type all the HTML out more than once when creating the pages. Maybe we should create one page, and cut-and-paste the rest.
But let's think a bit further. Suppose the boss asked us to add a new element to the menu: tour dates. We'd have to edit every page, and make sure we made the same change everywhere. If the boss then asked us to add another menu item, albums, we'd have to do the same thing. If the boss asked us to add another menu item, we'd quit and go live in a small hut in the woods.
Let's do things a bit differently. Let's create a file called template_front.php, and put this in it:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<title>Evil Squirrels T-Shirts: <?php print $subtitle; ?></title>
<link type="text/css" rel="stylesheet" href="lib/screen.css">
</head>
<body>
<div id="header">
<h1>Evil Squirrels T-Shirts</h1>
<h2><?php print $subtitle; ?></h2>
</div>
<div id="menu">
<ul>
<li><a href="./">Home</a></li>
</ul>
<ul>
<li><a href="mapa.php">Mapa</a></li>
</ul>
<ul>
<li><a href="meehee.php">Meehee</a></li>
</ul>
<ul>
<li><a href="miki.php">Miki</a></li>
</ul>
<ul>
<li><a href="moto.php">Moto</a></li>
</ul>
<ul>
<li><a href="muhu.php">Muhu</a></li>
</ul>
<ul>
<li><a href="mysy.php">Mysy</a></li>
</ul>
<ul>
<li><a href="shopping_cart.php">Shopping cart</a></li>
</ul>
</div>
<div id="content">
It's mostly HTML, with two bits of PHP: in the <title> tag, and in the <h2>. Both pieces of PHP output the variable $subtitle. Hmmm....
Then let's create another file called template_end.php, and put this in it:
<div id="footer">
<p>No rights reserved, except for the squirrel images, which belong
to <a href="http://zombiecatfire13.deviantart.com/"
target="_blank">Zombiecatfire13</a>.</p>
</div>
</body>
</html>
There isn't any PHP here.
Now, let's create a third file that uses these two, called template_standard.php:
<?php
$subtitle = '';
require_once 'lib/template_front.php';
?>
<!-- Content goes here -->
<?php
require_once 'lib/template_end.php';
?>
This gives us a template we can use for every page. First, we set the variable $subtitle to something, and add the contents of template_front.php. template_front.php will show the value of $subtitle in the <title> and <h2>. Then we put in the main content, the stuff that's different for each page. Finally, we output the footer.
To create a new page, we copy template_standard.php, and change it. Here's what index.php looks like:
<?php
$subtitle = 'Welcome';
require_once 'lib/template_front.php';
?>
<p>Evil Squirrels. You know them, you fear them.</p>
<p>Now wear them.</p>
<p align="center">
<a href="mapa.php">
<img class="squirrel_image_link" src="tshirt_images/mapa_small.jpg"
alt="Mapa" title="Mapa" width="125" height="150">
</a>
<a href="meehee.php">
<img class="squirrel_image_link" src="tshirt_images/meehee_small.jpg"
alt="Mehee" title="Mehee" width="100" height="150">
</a>
<a href="miki.php">
<img class="squirrel_image_link" src="tshirt_images/miki_small.jpg"
alt="Miki" title="Miki" width="113" height="150">
</a>
</p>
<p align="center">
<a href="moto.php">
<img class="squirrel_image_link" src="tshirt_images/moto_small.jpg"
alt="Moto" title="Moto" width="100" height="150">
</a>
<a href="muhu.php">
<img class="squirrel_image_link" src="tshirt_images/muhu_small.jpg"
alt="Muhu" title="Muhu" width="100" height="150">
</a>
<a href="mysy.php">
<img class="squirrel_image_link" src="tshirt_images/mysy_small.jpg"
alt="Mysy" title="Mysy" width="125" height="150">
</a>
</p>
<?php
require_once 'lib/template_end.php';
?>
Here comes the boss. Time to add a menu item. But there isn't any menu code in index.php. It's read in from template_front.php. Same for mapa.php, meehee.php, shopping_cart.php, and every other page. They all get their menu code from the same file: template_front.php. There is only one copy of the menu code across the entire site, even though it appears on every page.
We can add the new menu item by changing just one file. And every page on the site shows the new menu item. Wahoo!
Isn't PHP grand?
We can take it a step further. Go back to your browser, and compare the HTML code for, say, mapa.php and meehee.php. Here is part of each one:
<script type="text/javascript" src="lib/jquery-1.3.min.js"></script>
<script type="text/javascript">
$(document).ready(function(){
$('#quantity').focus();
});
function validate() {
var num_shirts = $('#quantity').val();
if ( num_shirts == '' || isNaN(num_shirts) || num_shirts < 1 ) {
alert('Please enter the number of shirts you want to buy.');
$('#quantity').focus();
return false;
}
return true;
}
</script>
<form method="post" action="shopping_cart.php" onSubmit="return validate()">
<label for="quantity">Number to buy</label>
<input type="text" size="3" id="quantity" name="quantity"
title="How many do you want?" value="0"><br>
<p><button type="submit">Add to cart</button></p>
<input type="hidden" name="squirrel_name"
value="mapa">
</form>
and
<script type="text/javascript" src="lib/jquery-1.3.min.js"></script>
<script type="text/javascript">
$(document).ready(function(){
$('#quantity').focus();
});
function validate() {
var num_shirts = $('#quantity').val();
if ( num_shirts == '' || isNaN(num_shirts) || num_shirts < 1 ) {
alert('Please enter the number of shirts you want to buy.');
$('#quantity').focus();
return false;
}
return true;
}
</script>
<form method="post" action="shopping_cart.php" onSubmit="return validate()">
<label for="quantity">Number to buy</label>
<input type="text" size="3" id="quantity" name="quantity"
title="How many do you want?" value="0"><br>
<p><button type="submit">Add to cart</button></p>
<input type="hidden" name="squirrel_name"
value="meehee">
</form>
They are almost identical. Can you find the difference?
Time for some more templating. Let's create this in the file template_order_form.php:
<script type="text/javascript" src="lib/jquery-1.3.min.js"></script>
<script type="text/javascript">
$(document).ready(function(){
$('#quantity').focus();
});
function validate() {
var num_shirts = $('#quantity').val();
if ( num_shirts == '' || isNaN(num_shirts) || num_shirts < 1 ) {
alert('Please enter the number of shirts you want to buy.');
$('#quantity').focus();
return false;
}
return true;
}
</script>
<form method="post" action="shopping_cart.php" onSubmit="return validate()">
<label for="quantity">Number to buy</label>
<input type="text" size="3" id="quantity" name="quantity"
title="How many do you want?" value="<?php print $quantity; ?>"><br>
<p><button type="submit">Add to cart</button></p>
<input type="hidden" name="squirrel_name"
value="<?php print $squirrel_name; ?>">
</form>
There's only two bits of PHP. Here is mapa.php:
<?php
session_start();
$subtitle = 'Mapa';
require_once 'lib/template_front.php';
?>
<p>
<img id="order_form_image" src="tshirt_images/mapa.jpg" title="Mapa">
Mapa groans for your blood. You must wear his t-shirt.
</p>
<p>Mapa's t-shirts cost $15 each.</p>
<?php
//Add the order form.
$squirrel_name = 'mapa';
$quantity = $_SESSION['mapa_quantity'];
require_once 'lib/template_order_form.php';
require_once 'lib/template_end.php';
?>
Here is meehee.php:
<?php
session_start();
$subtitle = 'Meehee';
require_once 'lib/template_front.php';
?>
<p>
<img id="order_form_image" src="tshirt_images/meehee.jpg" title="Meehee">
Meehee yearns to eat your liver. Fried, with onions.
</p>
<p>Wear her, or else.</p>
<p>Meehee's t-shirts cost $18 each.</p>
<?php
//Add the order form.
$squirrel_name = 'meehee';
$quantity = $_SESSION['meehee_quantity'];
require_once 'lib/template_order_form.php';
require_once 'lib/template_end.php';
?>
Neither of these files have much in them, but they both generate pages complete with menus, headings, order forms, and validation code. And we can change every form by editing one file.
Life is good.
The template pattern is one of the most important in the Web developer's toolkit. When you have bunches o' stuff that is mostly the same, think "template."
The shopping cart
Here is the code for one of the order forms, after the templates have done their work:
<form method="post" action="shopping_cart.php" onSubmit="return validate()">
<label for="quantity">Number to buy</label>
<input type="text" size="3" id="quantity" name="quantity"
title="How many do you want?" value="0"><br>
<p><button type="submit">Add to cart</button></p>
<input type="hidden" name="squirrel_name"
value="meehee">
</form>
There are two <input> fields, but the user sees only one. The user enters the quantity, and clicks Add. The form passes the quantity and the value of the hidden field, squirrel_name, to shopping_cart.php. So the shopping cart program gets two pieces of data: the name of the squirrel, and the number to order.
The cart information is kept in session variables. $_SESSION['mapa_quantity'] holds the number of Mapa t-shirts ordered, $_SESSION['meehee_quantity'] holds the number of Meehee t-shirts ordered, and so on.
Let's see how the shopping cart works.
<?php
session_start(); 1
$subtitle = 'Shopping Cart';
require_once 'lib/template_front.php';
//Get form data.
$squirrel_name = $_POST['squirrel_name']; 2
$quantity = $_POST['quantity'];
//Add to the cart.
switch($squirrel_name) { 3
case 'mapa':
$_SESSION['mapa_quantity'] = $quantity;
break;
case 'meehee':
$_SESSION['meehee_quantity'] = $quantity;
break;
case 'miki':
$_SESSION['miki_quantity'] = $quantity;
break;
case 'moto':
$_SESSION['moto_quantity'] = $quantity;
break;
case 'muhu':
$_SESSION['muhu_quantity'] = $quantity;
break;
case 'mysy':
$_SESSION['mysy_quantity'] = $quantity;
break;
}
//Compute totals. 4
$mapa_total = $_SESSION['mapa_quantity'] * 15;
$meehee_total = $_SESSION['meehee_quantity'] * 18;
$miki_total = $_SESSION['miki_quantity'] * 22;
$moto_total = $_SESSION['moto_quantity'] * 16;
$muhu_total = $_SESSION['muhu_quantity'] * 18;
$mysy_total = $_SESSION['mysy_quantity'] * 24;
$overall_total = $mapa_total + $meehee_total + $miki_total 5
+ $moto_total + $muhu_total + $mysy_total;
//Show the cart.
?>
<script type="text/javascript" src="lib/jquery-1.3.min.js"></script>
<script type="text/javascript">
$(document).ready(function() {
$('#mt').click( function() {
location = 'mt_shopping_cart.php'; 6
});
});
</script>
<p>Here is your shopping cart.</p>
<table cellspacing="20">
<tr>
<th>Squirrel</th>
<th>Shirts</th>
<th>Price<br>each</th>
<th>Total</th>
</tr>
<tr>
<td>Mapa</td>
<td align="right"><?php print $_SESSION['mapa_quantity']; ?></td> 7
<td align="right">$15</td>
<td align="right">$<?php print $mapa_total; ?></td>
</tr>
<tr>
<td>Meehee</td>
<td align="right"><?php print $_SESSION['meehee_quantity']; ?></td>
<td align="right">$18</td>
<td align="right">$<?php print $meehee_total; ?></td>
</tr>
<tr>
<td>Miki</td>
<td align="right"><?php print $_SESSION['miki_quantity']; ?></td>
<td align="right">$22</td>
<td align="right">$<?php print $miki_total; ?></td>
</tr>
<tr>
<td>Moto</td>
<td align="right"><?php print $_SESSION['moto_quantity']; ?></td>
<td align="right">$16</td>
<td align="right">$<?php print $moto_total; ?></td>
</tr>
<tr>
<td>Muhu</td>
<td align="right"><?php print $_SESSION['muhu_quantity']; ?></td>
<td align="right">$18</td>
<td align="right">$<?php print $muhu_total; ?></td>
</tr>
<tr>
<td>Mysy</td>
<td align="right"><?php print $_SESSION['mysy_quantity']; ?></td>
<td align="right">$24</td>
<td align="right">$<?php print $mysy_total; ?></td>
</tr>
<tr>
<td>Total</td>
<td align="right"> </td>
<td align="right"> </td>
<td align="right">$<?php print $overall_total; ?></td>
</tr>
</table>
<p><button type="button" id="mt"
title="Remove everything from the shopping cart"> 8
Empty cart</button></p>
<?php
require_once 'lib/template_end.php';
?>
The session is started at 1. Remember that this needs to be done on every page where sessions are used. At 2, order information is taken from the form. It should be validated, though I've skipped this step for simplicity.
We need to add the new order quantity to the right session variable. The code at 3 does that. If you aren't familiar with the switch() statement, look it up on the Web. The code at 4 computes the total sales for each t-shirt type, and then the code at 5 works out the grand total. The <table> (7) shows the totals to the user.
The user is given a button that empties the shopping cart (9). When the user clicks it, the code at 6 is run. It jumps to another program, mt_shopping_cart.php. The code in that program empties the shopping cart.
Question:
Why not simply put the code to clear the shopping cart at 6? Why jump to another page?
Answer:
PHP code is run when a page is being created on the server. Once a page has been created, it's too late to run more PHP. So we jump to a new page, and that page empties the shopping cart as it's being run.
Note that Ajax changes this. Ajax lets us do server-side processing without leaving the page we're on. Ajax isn't covered in this course.
Here's what the page that empties the shopping cart looks like:
<?php
//MT the shopping cart.
session_start();
$_SESSION['mapa_quantity'] = 0;
$_SESSION['meehee_quantity'] = 0;
$_SESSION['miki_quantity'] = 0;
$_SESSION['moto_quantity'] = 0;
$_SESSION['muhu_quantity'] = 0;
$_SESSION['mysy_quantity'] = 0;
header('location:shopping_cart.php');
exit();
?>
The code sets all of the session variables to zero, and jumps back to the shopping cart.
This is a hassle
We've got a separate session variable for each product. It works, but what if there are a hundred products? Or 5,000?

Argh!
This just isn't going to work.
To do it right, we need arrays. That's coming up later.
Exercises
Exercise 1. A new squirrel
Munigetr joins the band. Add a page for him. His t-shirts cost $21. Use these images:

Exercise 2. Rating dogs
Write a program that lets users rate dogs. The screen starts off like this:

The rates the dogs by clicking on them. The first dog clicked is given a rating of one, the next dog is given a rating of two, etc. Once a dog has been clicked, it is not clickable again. Here's what the screen might look like after three clicks:
After 6 clicks, none of the dogs is clickable.