July 23, 2012
Where are we?
You know how to get data from a form, and validate it. You know how to use a validation function. Let’s improve the way that’s done. Again.
This lesson’s goals
By the end of this lesson, you should:
The form/processor pattern
Up to now, we’ve separated the page with the input form from the page that does validation and processing. Like this:
Pattern so far
Figure 1. Pattern so far
The
.hmtl
page has a
<form>.
The
action
attribute of the form has the name of the processing page. When the user clicks the
submit
button, the form data is sent to the processing page.
The processing page validates the data. If there is a problem, it shows a message to the user, and suggests going back to the order form again.
If all the form data is OK, the order is processed. This means telling the shipping department to send the order, processing payment, and other businessy things.
A new pattern
But there’s another way of doing things. The new pattern is to put both the form and the server-sidePHP validation code on the same page.
The strangest thing about this is that the page with the form submits data to itself.
A new pattern
Figure 2. A new pattern
This is helpful when you do both client-side and server-side validation, and want to show both types of errors to the user in the same way. The new pattern lets you be more consistent in the way you show errors to users.
The key to this is that the page works in two modes:
The page uses
if
statements to act differently, depending on which mode it’s in.
What are these “modes” you speak of?
Let’s be sure we know what I mean by “modes” here. You’re used to thinking about modes that are built in to devices. For example, you might have an SUV that works in two-wheel or four-wheel drive. Two different modes. You use a switch (or whatever) to choose the mode you want.
The engineers who designed the vehicle built those modes into it.
Another example is the camera in your cell phone. It can work in still photo mode. Or it can work in video mode, where it shoots movies. You choose the modes you want.
The engineers who designed the cell phone built those modes into it.
But when you write PHP, you are the engineer. You get to create modes yourself. You decide:
You do this by the way you write your code. There is no special “mode” statement in PHP. The modes are created by the way you put together
if
statements and other things.
Let’s see how all this works.
What the user sees
Here’s an empty order form, from
order.php.
Empty order form
Figure 3. Empty order form
Suppose the user enters some bad data into
order.php:
Bad data
Figure 4. Bad data
The form data is sent from
order.php to order.php;
the page sends the form data to itself. Here is what it shows:
Error messages
Figure 5. Error messages
Now, what if the user enters valid data?
Valid data
Figure 6. Valid data
Here is the result:
Order confirmation
Figure 7. Order confirmation
You can try it. Enter different combinations of good and bad data into the fields, and see what you get.
Some code
Here’s order.php.
01.<?php
02.if ( $_POST ) {
03.//There is order data to validate.
04.require 'validation-library.inc';
05.//Warning: Extra characters at the end of validation-library.inc
06.//will break this page!
07.//Get the order amounts.
08.$frisbees = $_POST['frisbees'];
09.$giant_chew_ropes = $_POST['giant_chew_ropes'];
10.//Validate input.
11.$error_message_frisbees = check_number_ordered($frisbees, 15);
12.$error_message_giant_chew_ropes = check_number_ordered($giant_chew_ropes, 10);
13.//Jump if no errors.
14.if ( $error_message_frisbees == '' && $error_message_giant_chew_ropes == '') {
15.$destination_url = "process.php?frisbees=$frisbees&giant_chew_ropes=$giant_chew_ropes";
16.header("Location:$destination_url");
17.exit();
18.}
19.}?><!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Strict//EN" "http://www.w3.org/TR/html4/strict.dtd">
20.<html>
21.<head>
22.<title>Order Form</title>
23.<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
24.</head>
25.<body>
26.<h1>Order Form</h1>
27.<?php
28.//Any error messages to display?
29.if ( $error_message_frisbees != '' ) {
30.print "<p>Frisbees: $error_message_frisbees</p>";
31.}
32.if ( $error_message_giant_chew_ropes != '' ) {
33.print "<p>Giant chew ropes: $error_message_giant_chew_ropes</p>";
34.}
35.?>
36.<form method="post" action="order.php">
37.<p>
38.Frisbees:
39.<input type="text" name="frisbees" size="3"
40.<?php
41.if ( $_POST['frisbees'] ) {
42.print ' value="' . $_POST['frisbees'] . '"';
43.}
44.?>
45.>
46.at $8.95 each
47.</p>
48.<p>
49.Giant chew ropes:
50.<input type="text" name="giant_chew_ropes" size="3"
51.<?php
52.if ( $_POST['giant_chew_ropes'] ) {
53.print ' value="' . $_POST['giant_chew_ropes'] . '"';
54.}
55.?>
56.>
57.at $12.95 each
58.</p>
59.<p>
60.<button type="submit">Order</button>
61.</p>
62.</form>
63.</body>
64.</html>
Figure 8. order.php
Line 2:
if ( $_POST ) {
checks whether there is any form data coming in. If there is no post data, then
$_POST
will be empty, which, in PHP, is lihe bring
false.
This is the mode check, if you want to think of it that way. If there is post data, we enter “check input” mode. Otherwise, we’re in “empty form” mode.
We created a validation function on the previous page. We’ll put it in a separate file, and bring it in like this (lines 4):
require 'validation-library.inc';
We’ll talk about the warning in lines 5 and 6 later.
Lines 8 and 9 get the form data into variables, as usual. Here’s one of the lines:
$frisbees = $_POST['frisbees'];
As before, the function
check_number_ordered()
checks the value passed in, and returns either an error message or a blank string (line 11):
$error_message_frisbees = check_number_ordered($frisbees, 15);
The next step is to check whether there are any errors. There were no errors if both the frisbees value and the giant ropes value were OK.
Here is the code:
14.if ( $error_message_frisbees == '' && $error_message_giant_chew_ropes == '') {
15.$destination_url = "process.php?frisbees=$frisbees&giant_chew_ropes=$giant_chew_ropes";
16.header("Location:$destination_url");
17.exit();
18.}
Part of Figure 8 (again). order.php
Line 14 has the test. Remember that the validation function
check_number_ordered()
returns an empty string. So that if both
$error_message_frisbees and $error_message_giant_chew_ropesare
empty strings, there were no errors.