Displaying Validation Warnings Another issue to consider is where to send the user when validation fails. So far we have assumed that a form submits to a processing script, and when one or more validation errors are found, the form prompts the user to use his or her browser's Back button to fix the errors. Not only does this create one more step for the user to take in order to complete the formand in an online store, you want as few obstacles between a customer and a completed order as possibleit can also sometimes cause the data in the form fields to be lost when Back is clicked. Whether the Back button causes data to be lost usually depends on the cache settings, either on the web server, in the user's browser, or at the user's Internet service provider. In many cases there is no problem. However, most notably when a PHP session has been started, no-cache headers are automatically sent to the browser, which causes data in form fields to be reset to their original values when you click the Back button. You will learn more about PHP sessions in Lesson 14, "Cookies and Sessions." A good technique is to have the form and processing script in the same file and have the form submit to itself. This way, if there are errors, they can be displayed on the same page as the form itself, and the previously entered values can be automatically defaulted into the form. Listing 13.1 shows a fairly complete example of a registration form, register.php. The name and email address fields are required, but the telephone number is optional. Listing 13.1. A Sample Registration Form with Required Fields <?php $required = array("name" => "Your Name", "email" => "Email Address"); foreach($required as $field => $label) { if (!$_POST[$field]) { $err .= "$label is a required field <br>"; } } if ($err) { echo $err; ?> <FORM ACTION="register.php" METHOD=POST> <TABLE BORDER=0> <TR> <TD>Your Name</TD> <TD><INPUT TYPE=TEXT SIZE=30 NAME="name" VALUE="<?php echo $_POST["name"];?>"></TD> </TR> <TR> <TD>Email Address</TD> <TD><INPUT TYPE=TEXT SIZE=30 NAME="email" VALUE="<?php echo $_POST["email"];?>"></TD> </TR> <TR> <TD>Telephone</TD> <TD><INPUT TYPE=TEXT SIZE=12 NAME="telephone" VALUE="<?php echo $_POST["telephone"];?>"></TD> </TR> </TABLE> <INPUT TYPE=SUBMIT VALUE="Register"> </FORM> <?php } else { echo "Thank you for registering"; } ?> Note that the warning messages in this example appears even if the form has not yet been submitted. This could be improved by also checking for the existence of the $_POST array in the script by using is_array, but the check for $err would also need to look for $_POST; otherwise, the form would never be displayed. The condition that checks $err spans the HTML form and, even though the PHP tags are closed around this chunk of HTML, the form is displayed only if that condition is true. In this example, after the form has been completed successfully, only a simple message is displayed. This is where you would do any processing based on the submitted data, such as storing it to a database, which you will learn about in Lesson 19, "Using a MySQL Database." Alternatively, the script could force the browser to redirect the user to another page automatically by using a Location HTTP header, as follows: header("Location: newpage.php"); Enforcing Data Rules You will often want to ensure not only that data is entered into required fields but that the quality of the data is good enough before proceeding. For instance, you might want to check that an email address or a phone number has the right format, using the rules developed in Lesson 8, "Regular Expressions." You could also enforce a minimum length on a field to make sure a user cannot just enter an x in each field to continue to the next page. Because each field will probably have a different validation rule, you cannot enforce data rules in a loop; you must instead write a rule for each field to be checked. However, when used in conjunction with the check for empty fields in a loop from the previous examples, you should also check that the value has been entered before doing any further validation. Otherwise, the warning message will first tell a user that a field is required and then also that it has been entered in the wrong format! The following rules could be added to Listing 13.1 after the required fields check to enforce suitable values for email address and telephone number: if ($_POST["email"] && !ereg("^[^@]+@([a-z0-9\-]+\.)+[a-z]{2,4}$", $_POST["email"])) $err .= "Email address format was incorrect <br>"; if ($_POST["telephone"] && !ereg("^\([[:digit:]]{3}\)[[:digit:]]{3}-[[:digit:]]{4}$", $_POST["telephone"])) $err .= "Telephone must be in format (555)555-5555 <br>"; Because these additional rules add new messages to $err if an error is found, the rest of the script remains unchanged. Highlighting Fields That Require Attention Rather than bombard the user with a list of warning messages, it's more user- friendly to highlight the fields in the form that require attention. The technique to use here is very similar to the previous example, but rather than append each warning message to $err, you should give each field its own warning text. If you use an array of warnings, it's simple to see whether the form has been successfully validated by counting the elements in $warnings. You write each rule to add an element to $warnings if validation of that field fails, as shown in the following example: if (!ereg("^[^@]+@([a-z\-]+\.)+[a-z]{2,4}$", $_POST["email"])) $warnings["email"] = "Invalid Format"; Then in the form itself, you can display this warning text next to the corresponding field: <TR> <TD>Email Address</TD> <TD><INPUT TYPE=TEXT SIZE=30 NAME="email" VALUE="<?php echo $_POST["email"];?>"></TD> <TD><b><?php echo $warnings["email"];?></b></TD> </TR> Listing 13.2 shows a revised register.php file that uses this technique to highlight missing or invalid field values. Listing 13.2. Form Validation Using Inline Warnings <?php $required = array("name" => "Your Name", "email" => "Email Address"); foreach($required as $field => $label) { if (!$_POST[$field]) { $warnings[$field] = "Required"; } } if ($_POST["email"] && !ereg("^[^@]+@([a-z\-]+\.)+[a-z]{2,4}$", $_POST["email"])) $warnings["email"] = "Invalid email"; if ($_POST["telephone"] && !ereg("^\([[:digit:]]{3}\)[[:digit:]]{3}-[[:digit:]]{4}$", $_POST["telephone"])) $warnings["telephone"] = "Must be (555)555-5555"; if (count($warnings) > 0) { ?> <FORM ACTION="register.php" METHOD=POST> <TABLE BORDER=0> <TR> <TD>Your Name</TD> <TD><INPUT TYPE=TEXT SIZE=30 NAME="name" VALUE="<?php echo $_POST["name"];?>"></TD> <TD><?php echo $warnings["name"];?></TD> </TR> <TR> <TD>Email Address</TD> <TD><INPUT TYPE=TEXT SIZE=30 NAME="email" VALUE="<?php echo $_POST["email"];?>"></TD> <TD><?php echo $warnings["email"];?></TD> </TR> <TR> <TD>Telephone</TD> <TD><INPUT TYPE=TEXT SIZE=12 NAME="telephone" VALUE="<?php echo $_POST["telephone"];?>"></TD> <TD><?php echo $warnings["telephone"];?></TD> </TR> </TABLE> <INPUT TYPE=SUBMIT VALUE="Register"> </FORM> <?php } else { echo "Thank you for registering"; } ?> The first loop assigns the warning text "Required" to any required field that is left blank. Each of the individual validation rules has its own warning text. How you highlight a field that requires attention is up to your imagination and creativity with HTML. For instance, by checking for the presence of an element in $warnings for each field, you could change the style of the input box to a shaded background, like so: <INPUT TYPE=TEXT SIZE=30 NAME="email" <?php if ($warnings["email"]) echo "STYLE=\"shaded\"";?> VALUE="<?php echo $_POST["email"];?>"> Summary In this lesson you have learned how to validate user input from HTML forms and how to present the form back to the user so that he or she can correct any errors. In the next lesson you will learn about cookies and sessions in PHP. Lesson 14. Cookies and Sessions This lesson examines two ways of passing data between pages of a website without requiring a form submission from one page to another: using cookies and using sessions.