SimpleshoPHP

Detailed Analysis - Part 8

tyvm.php

This version of the code is used for the demo store; you'll also need to use it to handle "abandoned" orders. The idea is to thank the nice customer, blow away the book bag, and call it a day. Call this cancel.php and copy it to tyvm.php as well:

<?
require_once("startme.inc");
if (! isset($_SESSION["xvalid"])) {
        header("Location: main.php");
        exit;
}

if (!($PHPSESSID)) {
        header("Location: main.php");
        exit;
}

# DEMO STORE ONLY - abandon bookbag by adding bag.qty back to books.stock

I could have done this very simply with a more current version of MySQL, but to my chagrin the version I've been using does not allow a "subselect" within an update. In other words, I can't say "update table1 set somefield = somefield + 1 where somefield in (select somefield otherfield from table1, table2)"

Well, where there's a whip there's a way. We can replace rows, getting the replacement from a temporary table, and we can create a temporary table and manipulate the values as we do so -- so, here's an ugly workaround for putting an entire book bag back into our books table:

$tmp1 = "create temporary table tmpx select title,author,isbn,publisher,\
 format,condition,books.sku,dept,price,stock+qty \
 from books,bag where books.sku=bag.sku and sess = '$PHPSESSID'";
$tmp2 = "replace books select * from tmpx";
$tmp3 = "drop table tmpx";

We're creating a temporary table with just the rows of the books table that match the ones in our book bag, and adding back the books we took out. Then we're replacing the existing rows in "books" with those updated rows, just to fix the value in the "stock" column.

$sql1 = mysql_query($tmp1,$connection) or die ("Couldn't create temp table");
$sql2 = mysql_query($tmp2,$connection) or die ("Couldn't update stock");
$sql3 = mysql_query($tmp3,$connection) or die ("Couldn't drop temp table");

Done with the book bag, so let's get rid of it:

$sql = "delete from bag where sess = '$PHPSESSID'";
$sql_result = mysql_query($sql,$connection)
        or die ("Couldn't clear your bookbag");
?>

And now we can shake our customer's hand and show her politely to the door:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head>
<link rel="stylesheet" href="simple.css">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Silk Purse Books - silkpursebooks.com</title>
</head>
<body bgcolor="#ffffff" >
<? $location="Thank You"; include("top.inc"); ?>
<!--- left --->
<tr>
<td>
<a href="main.php">Back to Main</a>
<!--- main --->
<td>
<center>
Your Bookbag&nbsp;&nbsp;-&nbsp;&nbsp;  
Check Out</a>&nbsp;&nbsp;-&nbsp;&nbsp;
<a href="aboutus.php">About Us</a>
</td>
</tr>
</table>
<table width="90%" align=center border=0 cellpadding=3>
<tr bgcolor="#e7f0ff">
<td>&nbsp</td></tr>
<tr><td>
<h1>Our "Thank you" page</h1>
<p>
As this is a demo store, any information you entered has been
safely discarded.</p>
</td>
<tr bgcolor="#e7f0ff">
<td>&nbsp</td></tr>
</table>
<!--- bottom --->
<? include("bottom.inc"); ?>
</body></html>

When you're ready to start processing orders, you will want to replace tyvm.php with this alternate version. It is much simpler, because it doesn't have to put things back into stock. Save cancel.php but replace tyvm.php with this code:


<?
require_once("startme.inc");
if (! isset($_SESSION["xvalid"])) {
        header("Location: main.php");
        exit;
}

$sql = "delete from bag where sess = '$PHPSESSID'";
$sql_result = mysql_query($sql,$connection)
        or die ("Couldn't clear your bookbag");
?>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head>
<link rel="stylesheet" href="simple.css">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>SimpleshoPHP Bookstore</title>
</head>
<body bgcolor="#ffffff" >

<? $location="Thank You"; include("top.inc"); ?>
<!--- left --->
<tr>
<td>
<a href="main.php">Back to Main</a>
<!--- main --->
<td>
<center>
Your Bookbag&nbsp;&nbsp;-&nbsp;&nbsp;  
Check Out</a>&nbsp;&nbsp;-&nbsp;&nbsp;
<a href="aboutus.html">About Us</a>
</td>
</tr>
</table>

<table width="90%" align=center border=0 cellpadding=3>
<tr bgcolor="#e7f0ff">
<td>&nbsp</td></tr>
<tr><td>
<h1>Thank you for your order...</h1>
<p>
Your order is being processed.  If you gave us your email address,
you will receive a note from us when your order has been shipped.</p>
<p>
Please come back soon.  We appreciate your business.
</p>
</td>

<tr bgcolor="#e7f0ff">
<td>&nbsp</td></tr>
</table>

<!--- bottom --->
<? include("bottom.inc"); ?>
</body></html>

You need cancel.php because some of your visitors are going to fill up a bookbag and then just rudely walk away without completing the order process. Eventually you'll run out of items to sell, because your stock will all be in abandoned bookbags.

Even if you hook up cancel.php to a cancel button, very few window shoppers will bother to press it. You'll have to check the database for abandoned bookbags every so often and process them yourself. That means you'll need a way to override the session_id variable. I figure that will be an enhancement, an admin page. We'll start by adding a timestamp to the bookbag so we know it's stale. The admin page will then capture those stale session id's and run them through the cancel.php code.

Oh, I almost forgot -- "message.html" is a standalone page which calls a conventional CGI program, MIT's cgiemail. This is a secure replacement for the old formmail CGI script -- you don't want formmail, which is being abused all over the Net. Cgiemail is an easy way to let people send you an email message without exposing your email address in a "mailto" link.

That's SimpleshoPHP from top to bottom. There is of course considerable room for improvement -- more of the common code could be reduced to include files, especially the "skin" or appearance features. Session information could be written to the database without compromising the user's privacy. The goal here, though, is to have a solid basis to add features. If we started with all of them, we'd be in the same boat as those not-so-simple shops where the "features" make it all but impossible to install anything except their provided demo store.


What now? We still have a few loose ends; populating the database, for one. (See below)


Summary

Detailed descriptions

SimpleshoPHP Home


You are invited to post comments or questions on the SimpleshoPHP forum at SourceForge.net.

SourceForge.net Logo


Copyright 2003-2005, Kevin Martin, dba Brass Cannon Consulting.
The project "SimpleshoPHP" is Free Software, distributed
under the LGPL as described at opensource.org