Form Handling with PHP

Lesson 3 - More Complex Forms & Messages

Index   Lesson << Prev 1 2 3 4 5 6 7 Next >>

So far, we've dealt with a very basic form using text and textarea controls. While that may fit your needs, you may also have occasion to deal with other types of input like lists, checkboxes, or radio buttons.

Let's begin by reiterating the purpose of the various controls. You would do well to restrain creativity and use these controls only the way they were designed. Departures from the original purposes make for confused users and mistakes.

There are two types of lists available. There is the drop down "combo box" and the fixed size "list box." The HTML term for both of these list is called a <select>. Both of these lists should be used for choosing from a relatively small number of options. Too many choices are overwhelming to the user. How many is too many? There is no hard and fast rule. You'll have to be the judge of that.

The drop down combo box looks like this: This type of list is intended for choosing one and only one item from a pre-defined list of items.
The fixed size list box looks like this: This type of list is intended for choosing one, or more items from a pre-defined list.
Check boxes look like this: Red
Green
Blue
Check boxes are intended for choosing yes, or no answers to particular items.
Radio buttons look like this:



Radio buttons are intended for choosing one and only one item from a small number of choices.

You will note from the above that there is a great deal of similarity between the purpose of the drop down combo box and radio buttons and also between the list box and check boxes. That's correct. You are free to choose whichever fits your design best. Of couse the list box can be configured to accept multiple selections. In that case, it's more like a group of check boxes

So how do you use these controls? Let's start with the combo box because it's the easiest. You just give it a name and read it's value just like you would with a text box. The list box is handled the same way except if you allow multiple selections. If the list box allows multiple selections, you must name it as an array. To do that, append opening and closing square brackets to what ever name you want to use. For example:

<select name="mylist[]" size="3">

When accepting values from a list box that allows multiple values you can then treat it as an array. For example, the following code snippet will display the number of items chosen and then list them:

<?php
   $listvals=$_POST['mylist'];
   $n=count($listvals);
   echo "User chose $n items from the list.<br>\n"
   for($i=0;$i<$n;$i++)
      echo "Item $i=".$listvals[$i]."<br>\n";
?>

Okay. Don't worry if you don't understand that just yet. We'll give you a more useful example later.

A major difference between checkboxes and radio buttons is that all radio buttons in a group should have the same name. Checkboxes should all have individual names that refer only to a specific checkbox. You get the value of the one and only radio button selected by testing the $_POST['radiobuttonname'] value. Checkboxes, on the other hand, will only be included in the $_POST array if they were checked.

Now, if you've got all that, let's add a few additional controls to our form and format them into our e-mail message. Paste this code into a PHP document, or download the source.

Disclaimer: I'll be the last one to claim that this form, or the code processing it are terribly elegant, or efficient. The purpose of this form is to illustrate a number of techniques to help you in your learning process. This script uses the value of the HTTP_REFERER to test for a legal form submission. As I mentioned earlier that's not the most reliable way to do it. For now, if you try this form and you get an "Invalid referer" error, remove the lines that test that. They are annotated in the code, but don't forget to continue to Lesson 7 where we discuss another method to protect your script.
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"
   "http://www.w3.org/TR/REC-html40/loose.dtd">
<html>
<head>
<title>Lesson 3</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
</head>
<body>
<?php
   if ($_SERVER['REQUEST_METHOD'] != 'POST'){
      $me = $_SERVER['PHP_SELF'];
?>
<h1 align="center">Widget Order Form</h1>
<form name="form1" method="post" action="<?=$me?>">
   <table border="0" align="center" cellpadding="5" cellspacing="0">
      <tr>
         <td align="right" valign="middle">Name:</td>
         <td><input name="Name" type="text" size="40">
         </td>
      </tr>
      <tr>
         <td align="right" valign="middle">Size:</td>
         <td><select name="size">
               <option value="small">Small</option>
               <option value="medium">Medium</option>
               <option value="large">Large</option>
            </select>
         </td>
      </tr>
      <tr>
         <td align="right" valign="middle">Options:</td>
         <td><select name="options[]" size="4" multiple id="options[]">
               <option value="magnifier">Magnifier</option>
               <option value="reducer">Reducer</option>
               <option value="timer">Timer</option>
               <option value="oscillator">Oscillator</option>
            </select>
         </td>
      </tr>
      <tr>
         <td align="right" valign="middle">Color:</td>
         <td><input type="radio" name="color" checked value="red">
            Red<br>
            <input type="radio" name="color" value="green">
            Green<br>
            <input type="radio" name="color" value="blue">
            Blue</td>
      </tr>
      <tr>
         <td align="right" valign="middle">Accessories:</td>
         <td><input name="extension" type="checkbox" 
            id="extension" value="extension">Extension<br>
            <input name="wallmount" type="checkbox"
            id="wallmount" value="wallmount">Wall Mount<br>
            <input name="deskmount" type="checkbox"
            id="deskmount" value="deskmount">Desk Mount</td>
      </tr>
      <tr>
         <td align="right" valign="top">Comments:</td>
         <td><textarea name="MsgBody" cols="40" rows="6"></textarea>
         </td>
      </tr>
      <tr>
         <td> </td>
         <td><input type="submit" name="Submit"
               value="Send">
         </td>
      </tr>
   </table>
</form>
<?php
   } else {
      error_reporting(0);
      // initialize a array to 
      //hold any errors we encounter
      $errors = array();

      // test to see if the form was actually 
      // posted from our form
      // In testing, if you get an Inavlid referer error
      // comment out or remove the next three lines
      $page = $_SERVER['HTTP_HOST'].$_SERVER['PHP_SELF'];
      if (!ereg($page, $_SERVER['HTTP_REFERER']))
         $errors[] = "Invalid referer";

      // check to see if a name was entered
      if (!$_POST['Name'])
         $errors[] = "Name is required";
      // if there are any errors, display them
      if (count($errors)>0) {
         foreach($errors as $err)
            echo "$err<br>\n";
         echo "<br>Please use your browser's Back button to fix.";
      } else {
         // no errors, so we build our message
         switch($_POST['color']){
            case 'red':
               $recipient = 'redperson@example.com';
               break;
            case 'green':
               $recipient = 'greenperson@example.com';
               break;
            case 'blue':
               $recipient = 'blueperson@example.com';
               break;
            default:
               $recipient = 'user@example.com';
         }
         $subject = "Widget On Line Order";
         $from = stripslashes($_POST['Name']);
         $msg = "Message sent by $from\n";
         $msg.="\nSize: ".$_POST['size'];
         $options=$_POST['options'];
         $msg.="\nOptions:";
         if ($options)
            for ($i=0;$i<count($options);$i++)
               $msg.= "\n- $options[$i]";
         else
            $msg.="\n- None";
         $msg.="\nColor: ".$_POST['color'];
         $extension=($_POST['extension'])?"Extension: Yes":"Extension: No";
         $wallmount=($_POST['wallmount'])?"Wallmount: Yes":"Wallmount: No";
         $deskmount=($_POST['deskmount'])?"Deskmount: Yes":"Deskmount: No";
         $msg.="\n$extension\n$wallmount\n$deskmount";
         $msg.="\n".stripslashes($_POST['MsgBody'])."\n";
         if (mail($recipient,$subject,$msg)){
            echo "<p>Thanks for your order!</p>";
            echo nl2br($msg);
         } else
            echo "An unknown error occurred.";
      }
   }
?>
</body>
</html>
         

So what's different about this form? It starts out just like our form in Lesson 1:

<?php
   if ($_SERVER['REQUEST_METHOD'] != 'POST'){
      $me = $_SERVER['PHP_SELF'];
?>

From there, everything is pure HTML until you get down to the next <?php line, where we pick up the ELSE condition for the IF started in the first PHP code block. The next few lines, you'll recognize as part of the validation that we developed in Lesson 2. In this instance, the MsgBody is not a required field, so we omitted the test for that and the Subject is hard coded, so we don't test that either.

First, we assign the recipient. Note that we're doing this dynamically. Here, we're using the color to decide who recieves the e-mail, which is unlikely, but will serve to illustrate the technique:

     switch($_POST['color']){
        case 'red':
           $recipient = 'redperson@example.com';
           break;
        case 'green':
           $recipient = 'greenperson@example.com';
           break;
        case 'blue':
           $recipient = 'blueperson@example.com';
           break;
        default:
           $recipient = 'user@example.com';
     }

We use the PHP SWITCH statement which allows selecting from multiple conditions. Since we have constructed our form using radio buttons for the color and have set one to be selected, we should never have a case where none of the buttons is chosen. However, if none were chosen and none of the first three CASE tests assigned the recipient, we've included a DEFAULT statement that will trigger if none of the preceding CASE statements is true.

Next we assign the subject, sender and the beginning of the message body to variables with the following code:

      $subject = "Widget On Line Order";
      $from = stripslashes($_POST['Name']);
      $msg = "Message sent by $from\n";

Next, we add the value of the Size drop down list:

      $msg.="\nSize: ".$_POST['size'];
	

Next, we test the values in the options list box. Our list box, in this example, allows multiple entries and passes the selected values to the script as an array. We process that array by appending any selected options to our $msg variable, like this:

      $options=$_POST['options'];
      $msg.="\nOptions:";
      if ($options)
         for ($i=0;$i<count($options);$i++)
            $msg.= "\n- $options[$i]";
      else
         $msg.="\n- None";

If the user didn't select any options, we explicitly show None. Now we add in the value of the user's choice of color:

         $msg.="\nColor: ".$_POST['color'];

The following lines test the value of the checkboxes and assign the results to variables:

         $extension=($_POST['extension'])?"Extension: Yes":"Extension: No";
         $wallmount=($_POST['wallmount'])?"Wallmount: Yes":"Wallmount: No";
         $deskmount=($_POST['deskmount'])?"Deskmount: Yes":"Deskmount: No";
         $msg.="\n$extension\n$wallmount\n$deskmount";
   

We test for each of them since, as mentioned, checkbox values do not appear unless the checkbox was actually checked. In this case, we want an explicit Yes or No answer for each of the checkboxes. The last line appends them to our message body.

Finally, we add in anything that may have been entered in the Comments area:

         $msg.="\n".stripslashes($_POST['MsgBody'])."\n";

The remaining lines simply call the PHP mail() function, just like we did in Lesson 1, except we display the information if the command was successful:

         if (mail($recipient,$subject,$msg)){
            echo "<p>Thanks for your order!</p>";
            echo nl2br($msg);
         } else
            echo "An unknown error occurred.";

The nl2br function preserves the line breaks in the message by replacing them with the HTML <br /> tag.

So that's all there is to it. You have a form that will send a formatted e-mail message with the result of the users' selections.

Lesson 4