In this section, we outline the customer
management scripts customer.1,
customer.2, and customer.3.
The customer.2 script is for data entry of
customer details and reporting errors and is based on the customer
<form>
case study from Chapter 6 and Chapter 8. The
customer.1 script performs data validation and
writes the customer details to the winestore database. It is also
based on the case study examples from Chapter 6 and Chapter 8. The
customer.3 receipt is designed to avoid the
reload problem after writing to the database.
Example 10-1 lists the customer.1 script. It is based on Example 8-4 and has the same structure with two exceptions:
It validates a superset of customer fields, that is, all the fields listed in Chapter 1.
It manages the encryption of passwords and user account allocation.
The validation techniques used for the additional fields—such as the telephone and fax numbers, email address, zip code, and so on—are discussed in Chapter 7.
Example 10-1. The complete winestore customer validation script, customer.2
<?php // This script validates customer data entered into // example.customer.2.php. // If validation succeeds, it INSERTs or UPDATEs // a customer and redirect to a receipt page; if it // fails, it creates error messages and these are later // displayed by example.customer.2.php. include 'include.inc'; set_error_handler("errorHandler"); // Initialize a session session_start( ); // Register an error array - just in case! if (!session_is_registered("errors")) session_register("errors"); // Clear any errors that might have been // found previously $errors = array( ); // Set up a $formVars array with the POST variables // and register with the session. if (!session_is_registered("formVars")) session_register("formVars"); foreach($HTTP_POST_VARS as $varname => $value) $formVars[$varname] = trim(clean($value, 50)); // Validate the firstName if (empty($formVars["firstName"])) // First name cannot be a null string $errors["firstName"] = "The first name field cannot be blank."; elseif (!eregi("^[a-z'-]*$", $formVars["firstName"])) // First name cannot contain white space $errors["firstName"] = "The first name can only contain alphabetic " . "characters or "-" or "'""; elseif (strlen($formVars["firstName"]) > 50) $errors["firstName"] = "The first name can be no longer than 50 " . "characters"; // Validate the Surname if (empty($formVars["surname"])) // the user's surname cannot be a null string $errors["surname"] = "The surname field cannot be blank."; elseif (strlen($formVars["surname"]) > 50) $errors["surname"] = "The surname can be no longer than 50 " . "characters"; // Validate the Address if (empty($formVars["address1"]) && empty($formVars["address2"]) && empty($formVars["address3"])) // all the fields of the address cannot be null $errors["address"] = "You must supply at least one address line."; else { if (strlen($formVars["address1"]) > 50) $errors["address1"] = "The address line 1 can be no longer " . "than 50 characters"; if (strlen($formVars["address2"]) > 50) $errors["address2"] = "The address line 2 can be no longer " . "than 50 characters"; if (strlen($formVars["address3"]) > 50) $errors["address3"] = "The address line 3 can be no longer " . "than 50 characters"; } // Validate the user's Initial if (!empty($formVars["initial"]) && !eregi("^[a-z]{1}$", $formVars["initial"])) // If there is a middle initial, it must be // one character in length $errors["initial"] = "The initial field must be empty or one " . "character in length."; // Validate the City if (empty($formVars["city"])) // the user's city cannot be a null string $errors["city"] = "You must supply a city."; elseif (strlen($formVars["city"]) > 20) $errors["city"] = "The city can be no longer than 20 characters"; // Validate State - any string less than 21 characters if (strlen($formVars["state"]) > 20) $errors["state"] = "The state can be no longer than 20 characters"; // Validate Zipcode if (!ereg("^([0-9]{4,5})$", $formVars["zipcode"])) $errors["zipcode"] = "The zipcode must be 4 or 5 digits in length"; // Validate Country if (strlen($formVars["country"]) > 20) $errors["country"] = "The country can be no longer than 20 characters"; // Phone is optional, but if it is entered it must have // correct format $validPhoneExpr = "^([0-9]{2,3}[ ]?)?[0-9]{4}[ ]?[0-9]{4}$"; if (!empty($formVars["phone"]) && !ereg($validPhoneExpr, $formVars["phone"])) $errors["phone"] = "The phone number must be 8 digits in length, " . "with an optional 2 or 3 digit area code"; // Fax is optional, but if it is entered it must // have correct format if (!empty($formVars["fax"]) && !ereg($validPhoneExpr, $formVars["fax"])) $errors["fax"] = "The fax number must be 8 digits in length, with " . "an optional 2 or 3 digit area code"; // Validate Date of Birth if (empty($formVars["dob"])) // the user's date of birth cannot be a null string $errors["dob"] = "You must supply a date of birth."; elseif (!ereg("^([0-9]{2})/([0-9]{2})/([0-9]{4})$", $formVars["dob"], $parts)) // Check the format $errors["dob"] = "The date of birth is not a valid date in the " . "format DD/MM/YYYY"; elseif (!checkdate($parts[2],$parts[1],$parts[3])) $errors["dob"] = "The date of birth is invalid. Please check " . "that the month is between 1 and 12, and the " . "day is valid for that month."; elseif (intval($parts[3]) < 1890) // Make sure that the user has a reasonable birth year $errors["dob"] = "You must be alive to use this service!"; elseif // Check whether the user is 18 years old. // If all the following are NOT true, then report // an error. // Were they born more than 19 years ago? (!((intval($parts[3]) < (intval(date("Y") - 19))) || // No, so were they born exactly 18 years ago, and // has the month they were born in passed? (intval($parts[3]) == (intval(date("Y")) - 18) && (intval($parts[2]) < intval(date("m")))) || // No, so were they born exactly 18 years ago in this // month, and was the day today or earlier in the month? (intval($parts[3]) == (intval(date("Y")) - 18) && (intval($parts[2]) == intval(date("m"))) && (intval($parts[1]) <= intval(date("d")))))) $errors["dob"] = "You must be 18+ years of age to use this ". "service."; // Only validate email if this is an INSERT if (!session_is_registered("loginUsername")) { // Check syntax $validEmailExpr = "^[0-9a-z~`!#$%&_-]([.]?[0-9a-z~!#$%&_-])*" . "@[0-9a-z~!#$%&_-]([.]?[0-9a-z~!#$%&_-])*$"; if (empty($formVars["email"])) // the user's email cannot be a null string $errors["email"] = "You must supply an email address."; elseif (!eregi($validEmailExpr, $formVars["email"])) // The email must match the above regular // expression $errors["email"] = "The email address must be in the " . "name@domain format."; elseif (strlen($formVars["email"]) > 50) // The length cannot exceed 50 characters $errors["email"] = "The email address can be no longer than " . "50 characters."; elseif (!(getmxrr(substr(strstr($formVars["email"], '@'), 1), $temp)) || checkdnsrr(gethostbyname( substr(strstr($formVars["email"], '@'), 1)),"ANY")) // There must be a Domain Name Server (DNS) // record for the domain name $errors["email"] = "The domain does not exist."; else { // Check if the email address is already in use in // the winestore if (!($connection = @ mysql_pconnect($hostName, $username, $password))) showerror( ); if (!mysql_select_db($databaseName, $connection)) showerror( ); $query = "SELECT * FROM users WHERE user_name = '" . $formVars["email"] . "'"; if (!($result = @ mysql_query ($query, $connection))) showerror( ); // Is it taken? if (mysql_num_rows($result) == 1) $errors["email"] = "A customer already exists with this " . "login name."; } } // Only validate password if this is an INSERT // Validate password - between 6 and 8 characters if (!session_is_registered("loginUsername") && (strlen($formVars["loginPassword"]) < 6 || strlen($formVars["loginPassword"] > 8))) $errors["loginPassword"] = "The password must be between 6 and 8 " . "characters in length"; // Now the script has finished the validation, // check if there were any errors if (count($errors) > 0) { // There are errors. Relocate back to the // customer <form> header("Location: example.customer.2.php"); exit; } // If we made it here, then the data is valid if (!isset($connection)) { if (!($connection = @ mysql_pconnect($hostName, $username, $password))) showerror( ); if (!mysql_select_db($databaseName, $connection)) showerror( ); } // Reassemble the date of birth into database format $dob = ""$parts[3]-$parts[2]-$parts[1]""; // Is this an update? if (session_is_registered("loginUsername")) { $custID = getCustomerID($loginUsername, $connection); $query = "UPDATE customer SET ". "title = "" . $formVars["title"] . "", " . "surname = "" . $formVars["surname"] . "", " . "firstname = "" . $formVars["firstName"] . "", " . "initial = "" . $formVars["initial"] . "", " . "addressline1 = "" . $formVars["address1"] . "", " . "addressline2 = "" . $formVars["address2"] . "", " . "addressline3 = "" . $formVars["address3"] . "", " . "city = "" . $formVars["city"] . "", " . "state = "" . $formVars["state"] . "", " . "zipcode = "" . $formVars["zipcode"] . "", " . "country = "" . $formVars["country"]. "", " . "phone = "" . $formVars["phone"] . "", " . "fax = "" . $formVars["fax"] . "", " . "birth_date = " . $dob . " WHERE cust_id = $custID"; } else $query = "INSERT INTO customer VALUES (NULL, " . """ . $formVars["surname"] . "", " . """ . $formVars["firstName"] . "", " . """ . $formVars["initial"] . "", " . """ . $formVars["title"] . "", " . """ . $formVars["address1"] . "", " . """ . $formVars["address2"] . "", " . """ . $formVars["address3"] . "", " . """ . $formVars["city"] . "", " . """ . $formVars["state"] . "", " . """ . $formVars["zipcode"] . "", " . """ . $formVars["country"] . "", " . """ . $formVars["phone"] . "", " . """ . $formVars["fax"] . "", " . """ . $formVars["email"] . "", " . $dob . ", " . 0 . ")"; // Run the query on the customer table if (!(@ mysql_query ($query, $connection))) showerror( ); // If this was an INSERT, we need to INSERT // also into the users table if (!session_is_registered("loginUsername")) { // Get the customer id that was created $custID = @ mysql_insert_id($connection); // Use the first two characters of the // email as a salt for the password $salt = substr($formVars["email"], 0, 2); // Create the encrypted password $stored_password = crypt($formVars["loginPassword"], $salt); // Insert a new user into the user table $query = "INSERT INTO users SET cust_id = $custID, password = '$stored_password', user_name = '" . $formVars["email"] . "'"; if (!($result = @ mysql_query ($query, $connection))) showerror( ); // Log the user into their new account session_register("loginUsername"); $loginUsername = $formVars["email"]; } // Clear the formVars so a future <form> is blank session_unregister("formVars"); session_unregister("errors"); // Now show the customer receipt header("Location: example.customer.3.php?custID=$custID"); ?>
The following fragment of Example 10-1 manages the creation of a new user account but only if this is a new customer:
if (!session_is_registered("loginUsername")) { // Get the customer id that was created $custID = @ mysql_insert_id($connection); // Use the first two characters of the // email as a salt for the password $salt = substr($formVars["email"], 0, 2); // Create the encrypted password $stored_password = crypt($formVars["loginPassword"], $salt); // Insert a new user into the user table $query = "INSERT INTO users SET cust_id = $custID, password = '$stored_password', user_name = '" . $formVars["email"] . "'"; if (!($result = @ mysql_query ($query, $connection))) showerror( ); // Log the user into their new account session_register("loginUsername"); $loginUsername = $formVars["email"]; }
The session variable loginUsername
indicates
whether or not the user is logged in. Therefore, the fragment adds a
new row to the users table only if the user
isn’t logged in. To store the password, the
techniques from Chapter 9 are applied, and the
password is encrypted using crypt( )
with
the first two characters of the email address as the seed. After
adding the row, the user is logged in by registering the session
variable loginUsername
and assigning the email
address value to it.
For updates of customer details, the external function
getCustomerID( )
is called prior to updating the row. The
function returns the customer cust_id
associated
with the loginUsername
session variable passed as
a parameter. The function is defined in the
include.inc
file.
If validation fails in Example 10-1, the script
redirects to the customer.2 script shown in
Example 10-2. Any validation error messages are
recorded in the array errors
and this array is
used to display the messages interleaved with the customer
<form>
widgets. If validation and the
database write succeed, the script redirects to the
customer.3 script shown in Example 10-3.
The script customer.2
is shown in Example 10-2. The script displays a
<form>
for customer data entry. If the user
is logged in and validation has not previously failed, the customer
data is retrieved from the customer table and
used to populate the <form>
widgets. If the
user isn’t logged in, and validation has not
previously failed, a blank <form>
is shown
to collect new member details. If data has failed validation, the
formVars
array that is registered as a session
variable is used to repopulate the <form>
,
and the error messages from the errors
array are
displayed.
Two external functions from include.inc
are used
in Example 10-2:
void
showMessage( )
This function outputs any errors or notices created by other scripts. These messages include login errors, cart update problems, ordering problems, etc.
void
showLogin( )
This function outputs in the top-right corner of the browser whether the user is logged in or not. If the user is logged in, it outputs his email address.
The country
widget has only three possible values:
Australia, United States, and Zimbabwe, In a full implementation of
our case study, a database table of country names would be
maintained, and the function selectDistinct( )
would present the
<select>
list. The function
selectDistinct( )
is discussed in Chapter 5.
Example 10-2. The customer <form> script customer.1
<?php // This script shows the user a customer <form>. // It can be used both for INSERTing a new customer and // for UPDATE-ing an existing customer. If the customer // is logged in, then it is an UPDATE; otherwise, an // INSERT. // The script also shows error messages above widgets // that contain erroneous data; errors are generated // by example.customer.1.php include 'include.inc'; set_error_handler("errorHandler"); // Show an error in a red font function fieldError($fieldName, $errors) { if (isset($errors[$fieldName])) echo "<font color="red">" . $errors[$fieldName] . "</font><br>"; } // Connect to a session session_start( ); // Is the user logged in and were there no errors from // a previous validation? // If so, look up the customer for editing if (session_is_registered("loginUsername") && empty($errors)) { if (!($connection = @ mysql_pconnect($hostName, $username, $password))) showerror( ); if (!mysql_select_db($databaseName, $connection)) showerror( ); $custID = getCustomerID($loginUsername, $connection); $query = "SELECT * FROM customer WHERE cust_id = " . $custID; if (!($result = @ mysql_query($query, $connection))) showerror( ); $row = mysql_fetch_array($result); // Reset $formVars, since we're loading from // the customer table $formVars = array( ); // Reset the errors $errors = array( ); // Load all the form variables with customer data $formVars["title"] = $row["title"]; $formVars["surname"] = $row["surname"]; $formVars["firstName"] = $row["firstname"]; $formVars["initial"] = $row["initial"]; $formVars["address1"] = $row["addressline1"]; $formVars["address2"] = $row["addressline2"]; $formVars["address3"] = $row["addressline3"]; $formVars["city"] = $row["city"]; $formVars["state"] = $row["state"]; $formVars["zipcode"] = $row["zipcode"]; $formVars["country"] = $row["country"]; $formVars["phone"] = $row["phone"]; $formVars["fax"] = $row["fax"]; $formVars["email"] = $row["email"]; $formVars["dob"] = $row["birth_date"]; $formVars["dob"] = substr($formVars["dob"], 8, 2) . "/" . substr($formVars["dob"], 5, 2) . "/" . substr($formVars["dob"], 0, 4); } ?> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd" > <html> <head><title>Customer Details</title></head> <body bgcolor="white"> <?php // Show the user login status showLogin( ); ?> <form method="post" action="example.customer.1.php"> <h1>Customer Details</h1> <?php // Display any messages to the user showMessage( ); // Show meaningful instructions for UPDATE or INSERT if (session_is_registered("loginUsername")) echo "<h3>Please amend your details below as " . "required. Fields shown in " . "<font color="red">red</font> are " . "mandatory.</h3>"; else echo "<h3>Please fill in the details below to " . "join. Fields shown in " . "<font color="red">red</font> are ". "mandatory.</h3>"; ?> <table> <col span="1" align="right"> <tr><td><font color="red">Title:</font></td> <td><select name="title"> <option <?php if ($formVars["title"]=="Mr") echo "selected";?>>Mr <option <?php if ($formVars["title"]=="Mrs") echo "selected";?>>Mrs <option <?php if ($formVars["title"]=="Ms") echo "selected";?>>Ms <option <?php if ($formVars["title"]=="Dr") echo "selected";?>>Dr </select><br></td> </tr> <tr><td><font color="red">First name:</font></td> <td><? echo fieldError("firstName", $errors); ?> <input type="text" name="firstName" value="<? echo $formVars["firstName"]; ?>" size=50></td> </tr> <tr><td><font color="red">Surname:</font></td> <td><? echo fieldError("surname", $errors); ?> <input type="text" name="surname" value="<? echo $formVars["surname"]; ?>" size=50></td> </tr> <tr><td>Initial: </td> <td><? echo fieldError("initial", $errors); ?> <input type="text" name="initial" value="<? echo $formVars["initial"]; ?>" size=1></td> </tr> <tr><td><font color="red">Address:</font></td> <td><? echo fieldError("address", $errors); ?> <? echo fieldError("address1", $errors); ?> <input type="text" name="address1" value="<? echo $formVars["address1"]; ?>" size=50></td> </tr> <tr><td></td> <td><? echo fieldError("address2", $errors); ?> <input type="text" name="address2" value="<? echo $formVars["address2"]; ?>" size=50></td> </tr> <tr><td></td> <td><? echo fieldError("address3", $errors); ?> <input type="text" name="address3" value="<? echo $formVars["address3"]; ?>" size=50></td> </tr> <tr><td><font color="red">City:</font></td> <td><? echo fieldError("city", $errors); ?> <input type="text" name="city" value="<? echo $formVars["city"]; ?>" size=20></td> </tr> <tr><td>State: </td> <td><? echo fieldError("state", $errors); ?> <input type="text" name="state" value="<? echo $formVars["state"]; ?>" size=20></td> </tr> <tr><td><font color="red">Zipcode:</font></td> <td><? echo fieldError("zipcode", $errors); ?> <input type="text" name="zipcode" value="<? echo $formVars["zipcode"]; ?>" size=5></td> </tr> <tr><td>Country: </td> <td><? echo fieldError("country", $errors); ?> <select name="country"> <option <?php if ($formVars["country"]=="Australia") echo "selected";?>>Australia <option <?php if ($formVars["country"]=="United States") echo "selected";?>>United States <option <?php if ($formVars["country"]=="Zimbabwe") echo "selected";?>>Zimbabwe </select></td> </tr> <tr><td>Telephone: </td> <td><? echo fieldError("phone", $errors); ?> <input type="text" name="phone" value="<? echo $formVars["phone"]; ?>" size=15></td> </tr> <tr><td>Fax: </td> <td><? echo fieldError("fax", $errors); ?> <input type="text" name="fax" value="<? echo $formVars["fax"]; ?>" size=15></td> </tr> <tr><td><font color="red">Date of birth (dd/mm/yyyy):</font> </td> <td><? echo fieldError("dob", $errors); ?> <input type="text" name="dob" value="<? echo $formVars["dob"]; ?>" size=10></td> </tr> <?php // Only show the username/email and password // <input> widgets to new users if (!session_is_registered("loginUsername")) { ?> <tr><td><font color="red">Email/username:</font></td> <td><? echo fieldError("email", $errors); ?> <input type="text" name="email" value="<? echo $formVars["email"]; ?>" size=50></td> </tr> <tr><td><font color="red">Password:</font></td> <td><? echo fieldError("loginPassword", $errors); ?> <input type="password" name="loginPassword" value="<? echo $formVars["loginPassword"]; ?>" size=8></td> </tr> <?php } ?> <tr> <td><input type="submit" value="Submit"></td> </tr> </table> </form> <br><a href="http://validator.w3.org/check/referer"> <img src="http://www.w3.org/Icons/valid-html401" height="31" width="88" align="right" border="0" alt="Valid HTML 4.01!"></a> </body> </html>
Example 10-3 shows the
customer receipt script, customer.3, that is
called after a database write to insert or update a customer. The
script is a receipt page that can be bookmarked—it expects a
cust_id
as a GET
method
parameter—and the script does nothing but read details from the
database. Reloading of the page therefore has no undesirable side
effects. Customer receipts can be viewed only when logged in, and a
user is permitted to view only her own customer receipts; if the user
attempts to retrieve another user’s details, a
warning message is shown to the user, and the
cust_id
is updated to be her own.
Example 10-3. The customer.3 customer receipt page
<?php // This script shows the user a receipt for their customer // UPDATE or INSERT. // It carries out no database actions and can be // bookmarked. The user must be logged in to view it. include 'include.inc'; set_error_handler("errorHandler"); // Show the user a customer INSERT or UPDATE receipt function show_HTML_receipt($custID, $connection) { $query = "SELECT * FROM customer WHERE cust_id = $custID"; if (!($result = @ mysql_query ($query, $connection))) showerror( ); // There is only one matching row $row = @ mysql_fetch_array($result); echo " <h1>Account details for " . "<font color="red">" . $row["email"] . "</font></h1> "; echo "<p><i>Please record your password " . "somewhere safe for future use</i> "; echo "<p>Your shipping and billing details are " . "as follows: <br><b> " . $row["title"] . " " . $row["firstname"] . " " . $row["initial"] . " " . $row["surname"] . " <br>" . $row["addressline1"] . " "; if ($row["addressline2"] != "") echo " <br>" . $row["addressline2"]; if ($row["addressline3"] != "") echo " <br>" . $row["addressline3"]; echo " <br>" . $row["city"] . " " . $row["state"] . " " . $row["zipcode"] . " <br>" . $row["country"] . "</b><br> "; if ($row["phone"] != "") echo " <br><b>Telephone: " . $row["phone"] . "</b>"; if ($row["fax"] != "") echo " <br><b>Fax: " . $row["fax"] . "</b>"; $row["dob"] = substr($row["birth_date"], 8, 2) . "/" . substr($row["birth_date"], 5, 2) . "/" . substr($row["birth_date"], 0, 4); echo " <br><b>Date of Birth: " . $row["dob"] . "</b> <br>"; } // Main ---------- // Re-establish the existing session session_start( ); // Check if the user is logged in - this should never // fail unless the script is run incorrectly if (!session_is_registered("loginUsername")) { session_register("message"); $message = "You must login to view your " . "customer receipt."; header("Location: example.cart.1.php"); exit; } // Check the correct parameters have been passed if (!isset($custID)) { session_register("message"); $message = "Incorrect parameters to " . "example.customer.3.php"; // Redirect the browser back to the calling page, // using the HTTP response header "Location:" // and the PHP environment variable $HTTP_REFERER header("Location: $HTTP_REFERER"); exit; } // Check this customer matches the custID if ($custID != getCustomerID($loginUsername, NULL)) { session_register("message"); $message = "You can only view your own " . "customer receipt!"; $custID = getCustomerID($loginUsername, NULL); } // Open a connection to the DBMS if (!($connection = @ mysql_pconnect($hostName, $username, $password))) showerror( ); if (!mysql_select_db($databaseName, $connection)) showerror( ); ?> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html401/loose.dtd"> <html> <head> <title>Hugh and Dave's Online Wines</title> </head> <body bgcolor="white"> <?php // Show the user login status showLogin( ); // Show the user any messages showMessage( ); // Show the customer confirmation show_HTML_receipt($custID, $connection); // Show buttons echo "<form action="example.cart.5.php"" . " method="GET">"; echo "<table>"; echo "<td><input type="submit" name="home"" . " value="Home"></td>"; ?> </table> </form> <br><a href="http://validator.w3.org/check/referer"><img src="http://www.w3.org/Icons/valid-html401" height="31" width="88" align="right" border="0" alt="Valid HTML 4.01!"></a> </body> </html>
3.133.146.47