A Simple Shopping Cart
This example will consist of two PHP scripts:a product catalogue, where you can add items to your shopping
cart
a check-out page, which displays the contents of the user’s
shopping cart for confirmation
From the check-out page, the order could then be submitted to a processing
system that would handle the details of accepting payment and shipping arrangements.
That system is beyond the scope of this book, and will not be discussed here.As in "Storing Binary Data in MySQL", we'll look at various
important fragments of code first and then I'll present the full script, so
don't bother typing any of the following snippets into your editor.Let’s start with the list of items we’ll have for sale in
our online store:
<table border="1">
<tr>
<th>Item Description</th>
<th>Price</th>
</tr>
<tr>
<td>Canadian-Australian Dictionary</td>
<td>$24.95</td>
</tr>
<tr>
<td>Used Parachute (never opened)</td>
<td>$1,000.00</td>
</tr>
<tr>
<td>Songs of the Goldfish (2CD Set)</td>
<td>$19.99</td>
</tr>
<tr>
<td>Ending PHP4 (O'Wroxey Press)</td>
<td>$34.95</td>
</tr>
</table>
<p>All prices are in imaginary dollars.</p>
Now, instead of hard-coding the items, we’ll place them in a PHP
array and generate the page dynamically. Arrays are created with the built-in
PHP function array, by listing the elements to
be included in the array as the parameters of the function. Items and their
prices would normally be stored in a database, but I’m using this method
so we can focus on sessions. You should already know all you need in order
to put together a database-driven product catalogue, so I’ll leave that
to you as an exercise.Here’s the code for our dynamically generated product catalogue:
<?php
$items = array( 'Canadian-Australian Dictionary',
'Used Parachute (never opened)',
'Songs of the Goldfish (2CD Set)',
'Ending PHP4 (O\'Wroxey Press)');
$prices = array( 24.95, 1000, 19.99, 34.95 );
?>
<table border="1">
<tr>
<th>Item Description</th>
<th>Price</th>
</tr>
<?php
for($i = 0; $i < count($items); $i++) {
echo('<tr>');
echo('<td>'.$items[$i].'</td>');
echo('<td>$'.number_format($prices[$i],2).'</td>');
echo('</tr>');
}
?>
</table>
<p>All prices are in imaginary dollars.</p>
This code produces the HTML we saw above. The table row for each item
is created using a for loop that counts through the $items array
(the function count returns the number of items in the
array). for loops were introduced in "Getting Started with PHP". We also use PHP’s built-in number_format function
to display the prices with two digits after the decimal point (see the PHP Manual for more information
about this function).Now, we’re going to store the list of items the user placed in
the shopping cart in yet another array. Because we’ll need this variable
to persist throughout a user’s visit to your site, we’ll store
it using PHP sessions. Here’s the code responsible for all this:
session_start();
if (!isset($_SESSION['cart']))
$_SESSION['cart'] = array();
session_start either starts a new session (and
sets the session ID cookie), or restores the variables registered in the existing
session, if one exists. The code then checks if $_SESSION['cart'] exits,
and, if not, initializes it to an empty array to represent the empty cart.We can now print out the number of items in the user’s shopping
cart:
<p>Your shopping cart contains
<?=count($_SESSION['cart'])?> items.</p>
Now, the user’s shopping cart is going to stay very empty if we
don’t provide a way to add items to it, so let’s modify the for loop
that displays our table of items, and enable it to provide a ‘Buy’
link on the end of each row:
<?php
for($i = 0; $i < count($items); $i++) {
echo('<tr>');
echo('<td>'.$items[$i].'</td>');
echo('<td>$'.number_format($prices[$i],2).'</td>');
echo('<td><a href="' . $_SERVER['PHP_SELF'] .
'?buy=' . $i . '">Buy</a></td>');
echo('</tr>');
}
?>
Now each product in our catalogue has a link back to the catalogue with buy=n in
the query string, where n is
the index of the item that’s to be added to the shopping cart in the $items array.
We can then watch for the $_GET['buy'] variable to appear
at the top of the page, and, when it does, we’ll add the item to the $_SESSION['cart'] array
before redirecting the browser back to the same page, but with no query string,
thereby ensuring that refreshing the page doesn’t repeatedly add the
item to the cart.
if (isset($_GET['buy'])) {
// Add item to the end of the $_SESSION['cart'] array
$_SESSION['cart'][] = $_GET['buy'];
header('location: ' . $_SERVER['PHP_SELF']);
exit();
}Now, this works just fine if the user has cookies enabled, but when
cookies are disabled, PHP’s automatic link adjustment doesn’t
affect the header function, so the session ID gets lost
at this point. Fortunately, if PHP identifies that cookies are disabled, it
creates a constant named SID, a string of the form PHPSESSID=somevalue,
which will pass on the session ID. We can make our code compatible with disabled
cookie support as follows:
if (isset($_GET['buy'])) {
// Add item to the end of the $_SESSION['cart'] array
$_SESSION['cart'][] = $_GET['buy'];
header('location: '. $_SERVER['PHP_SELF'] . '?' . SID);
exit();
}All that’s left is to add a ‘view your cart’ link
to the appropriate page, and we’ll have completed the catalogue script.
Here is the complete code for this page (—it’s
also available in the code archive).
<?php
session_start();
if (!isset($_SESSION['cart']))
$_SESSION['cart'] = array();
if (isset($_GET['buy'])) {
// Add item to the end of the $_SESSION['cart'] array
$_SESSION['cart'][] = $_GET['buy'];
header('location: ' . $_SERVER['PHP_SELF'] . '?' . SID);
exit();
}
?>
<html>
<head>
<title>Product catalogue</title>
</head>
<body bgcolor="#FFFFFF" text="#000000">
<p>Your shopping cart contains
<?=count($_SESSION['cart'])?> items.</p>
<p><a href=">View your cart</a></p>
<?php
$items = array( 'Canadian-Australian Dictionary',
'Used Parachute (never opened)',
'Songs of the Goldfish (2CD Set)',
'Ending PHP4 (O\'Wroxey Press)');
$prices = array( 24.95, 1000, 19.99, 34.95 );
?>
<table border="1">
<tr>
<th>Item Description</th>
<th>Price</th>
</tr>
<?php
for($i = 0; $i < count($items); $i++) {
echo('<tr>');
echo('<td>'.$items[$i].'</td>');
echo('<td>$'.number_format($prices[$i],2).'</td>');
echo('<td><a href="' . $_SERVER['PHP_SELF'] .
'?buy=' . $i . '">Buy</a></td>');
echo('</tr>');
}
?>
</table>
<p>All prices are in imaginary dollars.</p>
</body>
</html>
Now the code for is very similar to the
product catalogue. All it does is take the $_SESSION['cart'] variable
(after loading the session, of course), and use the numbers stored there to
print out the corresponding items from the $items array.
We also provide a link that loads the page with query string empty=1,
and causes the script to unset the $_SESSION['cart'] variable, which results
in a new, empty shopping cart. Here’s the code (also available in the
code archive):
<?php
session_start();
if (!isset($_SESSION['cart']))
$_SESSION['cart'] = array();
if (isset($_GET['empty'])) {
// Empty the $_SESSION['cart'] array
unset($_SESSION['cart']);
header('location: ' . $_SERVER['PHP_SELF'] . '?' . SID);
exit();
}
?>
<html>
<head>
<title>Shopping cart</title>
</head>
<body bgcolor="#FFFFFF" text="#000000">
<h1>Your Shopping Cart</h1>
<?php
$items = array( 'Canadian-Australian Dictionary',
'Used Parachute (never opened)',
'Songs of the Goldfish (2CD Set)',
'Ending PHP4 (O\'Wroxey Press)');
$prices = array( 24.95, 1000, 19.99, 34.95 );
?>
<table border="1">
<tr>
<th>Item Description</th>
<th>Price</th>
</tr>
<?php
$total = 0;
for($i = 0; $i < count($_SESSION['cart']); $i++) {
echo('<tr>');
echo('<td>'.$items[$_SESSION['cart'][$i]].'</td>');
echo('<td align="right">$');
echo(number_format($prices[$_SESSION['cart'][$i]],2));
echo('</td>');
echo('</tr>');
$total = $total + $prices[$_SESSION['cart'][$i]];
}
?>
<tr>
<th align="right">Total:</th><br />
<th align="right">$<?=number_format($total,2)?></th>
</tr>
</table>
<p><a href=">Continue Shopping</a> or
<a href="'PHP_SELF']?>?empty=1">Empty your cart</a>
</p>
</body>
</html>