PHP

Updating data

Updating data is usually a more complex process than inserting it. A three-step process for updates is used in most web database applications:

  1. Using a key value, matching data is read from the database.

  2. The data is presented to the user for modification.

  3. The data is updated by writing the modified data to the database, using the key value from the first step.

The first step of this process is usually user-driven: the user provides information that identifies the data to be updated. The information to identify the data-for example, a primary key value such as a cust_id-might be gathered in one of several ways:

  • It may be entered into a <form> by the user. For example, the user may be asked to type in or select from a list the customer identifier of the customer he wishes to modify.

  • It may be determined from another user-driven query. For example, the user might provide a surname and a first name through a <form>, and a SELECT query can then retrieve the unique customer identifier cust_id of that customer from the database (assuming the surname and first name combination is unique).

  • It may be formatted into an embedded link by a script. For example, you can produce a list of descriptions of regions from the winestore, where each entry in the list is a hypertext link that has the unique region identifier encoded as a query string.

These methods of gathering data from the user are discussed in Chapter 5. Here, let's assume that a primary key is provided through one of these techniques, and the value of the primary key has been encoded in an HTTP request that can be processed by the update script.

Step 1 is completed by retrieving the data that matches the primary key value provided by the user. Step 2 is to present the data to the user. To achieve this, a <form> is usually created that contains the values of each attribute that can be modified. In some cases, some attributes may not be presented to the user, and other values may require reformatting from their database representation for presentation. Reformatting is discussed in detail in Chapter 7.

In addition to presenting the data to the user, a method is required to store the primary key value associated with the data, because it is needed in Step 3 as a key to update the data. There are several approaches to maintaining this key across the three-step process, and one simple approach is presented in the next section.

Step 2 is complete when the user submits the <form> containing the modified data. Step 3 updates the database; this uses the same process as inserting new data.

Case study: Inserts and updates in practice

Example 6-7 shows a modified version of Example 6-5 that supports database updates. The script implements the first two steps of the three-step update process from the previous section. We discuss the third step later in this section.

Example 6-7. Allowing entry of new customer details and displaying customer details
<?php
  include 'db.inc';
  include 'error.inc';
  $custID = clean($custID, 5);
  // Has a custID been provided?
  // If so, retrieve the customer details for editing.
  if (!empty($custID))
  {
     if (!($connection = @ mysql_pconnect($hostName,
                                         $username,
                                         $password)))
        die("Could not connect to database");
     if (!mysql_select_db($databaseName, $connection))
        showerror(  );
     $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(  );
     // Load all the form variables with customer data
     $formVars["surname"] = $row["surname"];
     $formVars["firstName"] = $row["firstname"];
     $formVars["address1"] = $row["addressline1"];
     $formVars["city"] = $row["city"];
     $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">
<form method="post" action="example.6-8.php">
<h1>Customer Details</h1>
<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><input type="hidden" name="custID"
   value="<? echo $custID;?>"></td>
</tr>
<tr>
   <td><font color="red">First name:</font></td>
   <td><input type="text" name="firstName"
   value="<? echo $formVars["firstName"]; ?>" size=50></td>
</tr>
<tr>
   <td><font color="red">Surname:</font></td>
   <td><input type="text" name="surname"
   value="<? echo $formVars["surname"]; ?>" size=50></td>
</tr>
<tr>
   <td><font color="red">Address:</font></td>
   <td><input type="text" name="address1"
   value="<? echo $formVars["address1"]; ?>" size=50></td>
</tr>
<tr>
   <td><font color="red">City:</font></td>
   <td><input type="text" name="city"
   value="<? echo $formVars["city"]; ?>" size=20></td>
</tr>
<tr>
   <td><font color="red">Date of birth (dd/mm/yyyy):</font> </td>
   <td><input type="text" name="dob"
   value="<? echo $formVars["dob"]; ?>" size=10></td>
</tr>
<tr>
   <td><font color="red">Email/username:</font></td>
   <td><input type="text" name="email"
   value="<? echo $formVars["email"]; ?>" size=50></td>
</tr>
<tr>
   <td><input type="submit" value="Submit"></td>
</tr>
</table>
</form>
</body>
</html>

Step 1 of the update process works as follows. The script in Example 6-7 can process a custID passed through with an HTTP request. If the variable is set-for example, custID=1-this is an update operation. For an update, the script queries the database for the matching customer row and initializes variables with the results of the query. For example, when a surname is retrieved for a customer, the variable $formVars["surname"] is initialized with data from the database using:

$formVars["surname"] = $row["surname"]

This initialization of variables completes the first step of the update process.

The second step of the process-displaying the retrieved data for modification by the user-is achieved by modifying the <form>. We include throughout the <form> code in Example 6-7 short PHP scripts that initialize each <input> widget by setting the value attribute. For example, consider the HTML and PHP code fragment:

<tr>
   <td><font color="red">Surname:</font></td>
   <td><input type="text" name="surname"
   value="<? echo $formVars["surname"]; ?>" size=50></td>
</tr>

This fragment creates a text input widget to enter a surname and uses a short PHP fragment to prefill the widget with the value of the variable $formVars["surname"]. If the variable was initialized and isn't empty, the database value is displayed for editing by the user.

The second step of the process is completed by embedding the value of $custID in the <form> as a hidden input element. The $custID is embedded so it can be passed to the next script, where it then constructs the SQL query to perform the update operation. There are other ways this value can be passed through the three steps; these techniques are the subject of Chapter 8.

Example 6-8 implements the third step. The process is the same as inserting new data, with the exception of the SQL query that uses the $custID from the customer <form> to identify the row to be updated. The script not only supports updates but also supports the insert functionality of Example 6-6; if $custID isn't set, the data is inserted as a new row. As previously, after the database operation, the browser is redirected to a receipt page to avoid the reload problem. However, the update process is now susceptible to other problems that are described in the later section Section 6.2.

Example 6-8. Updating existing and inserting new customer rows
<?php
  include 'error.inc';
  include 'db.inc';
  $custID = clean($custID, 5);
  // Initialise an error string
  $errorString = "";
  // Clean and trim the POSTed values
  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
      $errorString .=
          "\n<br>The first name field cannot be blank.";
  // Validate the Surname
  if (empty($formVars["surname"]))
      // the user's surname cannot be a null string
      $errorString .=
          "\n<br>The surname field cannot be blank.";
  // Validate the Address
  if (empty($formVars["address1"]))
      // the user's address cannot be a null string
      $errorString .=
       "\n<br>You must supply at least one address line.";
  // Validate the City
  if (empty($formVars["city"]))
      // the user's city cannot be a null string
      $errorString .= "\n<br>You must supply a city.";
  // Validate Date of Birth
  if (empty($formVars["dob"]))
      // the user's date of birth cannot be a null string
   $errorString .= "\n<br>You must supply a date of birth.";
  elseif (!ereg("^([0-9]{2})/([0-9]{2})/([0-9]{4})$",
                 $formVars["dob"], $parts))
      // Check the format
      $errorString .=
        "\n<br>The date of birth is not a valid date " .
        " in the format DD/MM/YYYY";
  if (empty($formVars["email"]))
      // the user's email cannot be a null string
      $errorString .=
        "\n<br>You must supply an email address.";
  // Now the script has finished the validation,
  // check if there were any errors
  if (!empty($errorString))
  {
      // There are errors.  Show them and exit.
?>
<!DOCTYPE HTML PUBLIC
   "-//W3C//DTD HTML 4.0 Transitional//EN"
   "http://www.w3.org/TR/html4/loose.dtd" >
<html>
<head><title>Customer Details Error</title></head>
<body bgcolor="white">
<h1>Customer Details Error</h1>
<?=$errorString?>
<br>
<a href="example.6-7.php">Return to the customer form</a>
</body>
</html>
<?php
      exit;
  }
  // If we made it here, then the data is valid
  if (!($connection = @ mysql_pconnect($hostName,
                                       $username,
                                       $password)))
     die("Could not connect to database");
  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 (!empty($custID))
  {
     // Create a query to update the customer
     $query = "UPDATE customer SET ".
      "surname = \"" . $formVars["surname"] . "\", " .
      "firstname = \"" . $formVars["firstName"] . "\", " .
      "addressline1 = \"" . $formVars["address1"] . "\", " .
      "city = \"" . $formVars["city"] . "\", " .
      "email = \"" . $formVars["email"] . "\", " .
      "birth_date = " . $dob .
      " WHERE cust_id = $custID";
  }
  else
     // Create a query to insert the customer
     $query = "INSERT INTO customer
       set cust_id = NULL, " .
      "surname = \"" . $formVars["surname"] . "\", " .
      "firstname = \"" . $formVars["firstName"] . "\", " .
      "addressline1 = \"" . $formVars["address1"] . "\", " .
      "city = \"" . $formVars["city"] . "\", " .
      "email = \"" . $formVars["email"] . "\", " .
      "birth_date = $dob";
  // Run the query on the customer table
  if (!(@ mysql_query ($query, $connection)))
     showerror(  );
  // Is this an insert?
  if (empty($custID))
     // Find out the cust_id of the new customer
     $custID = mysql_insert_id(  );
  // Now show the customer receipt
  header("Location: customer_receipt.php?custID=$custID");
?>