Build Your Own Database-Driven Website Using PHP MySQL [Electronic resources]

Kevin Yank

نسخه متنی -صفحه : 190/ 94
نمايش فراداده

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();
}
?>
<l>
<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>
<l>

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();
}
?>
<l>
<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>
<l>