PHP Form Handling
by David Sklar,author of Learning PHP 5
08/26/2004
If your PHP program is a dynamic web page (and it probably is) and your PHP
program is dealing with user input (and it probably is), then you need to work
with HTML forms. Here are some tips for simplifying, securing, and organizing
your form-handling PHP code.
1. Use $_SERVER['PHP_SELF'] as a form action.
The $_SERVER auto-global array holds various useful server- and
request-specific info. The PHP_SELF element of $_SERVER holds the
filename of the currently executing script (relative to your web site's document
root directory). So, supplying $_SERVER['PHP_SELF'] as the
action attribute of the form tag makes the form submit to the same page
that displayed it. This lets you put the logic to handle the form in the same
page as the logic that displays it. For many simple forms, this keeps things
easy to manage.
2. Put [] at the end of the name of a multivalued form
parameter.
When you've got a form element like <select multiple> that can
submit multiple values to the server, put [] at the end of the form
element name so that the PHP interpreter knows to accept multiple values.
For example, consider this form:
<form method="POST" action="<?php echo $_SERVER['PHP_SELF']; ?>">
Pick some desserts: <select name="sweet[]" multiple>
<option value="puff"> Sesame Seed Puff</option>
<option value="square"> Coconut Milk Gelatin Square</option>
<option value="cake"> Brown Sugar Cake</option>
<option value="ricemeat"> Sweet Rice and Meat</option>
</select>
<input type="submit" name="Order">
</form>
If you pick Sesame Seed Puff and Brown Sugar Cake and
submit the form, then $_POST['sweet'] is itself an array.
$_POST['sweet'][0] is puff and $_POST['sweet'][1] is
cake. That's because the name attribute of the
<select> element is sweet[]. If the name was just
sweet, then $_POST['sweet'] would be a string, holding only
one of the selected values.
3. Test for form submission with a hidden element.
Include a hidden variable named, say, _submit_check in your forms
like this:
<input type="hidden" name="_submit_check" value="1"/>
Then, to test whether the form has been submitted, look for the
_submit_check element in $_POST:
if (array_key_exists('_submit_check', $_POST)) {
/* ... do something with the form parameters ... */
}
Testing for the presence of a hidden element avoids problems that can result
from browsers' varying behaviors when a user submits a form by pressing the Enter key
instead of clicking a submit button.
4. Divide your form handling into three parts: showing, validating, and
processing.
Logically, the life cycle of a web form usually comprises three steps:
showing the form, validating the submitted form parameters, and then processing
the submitted form parameters to generate appropriate output.
Dedicate a function to each of these steps: showing, validating, and
processing. With this modular design, deciding when each step needs to happen is
straightforward.
On many pages, the logical flow goes like this:
- If the request isn't a form submission, show the form.
- If the request is a form submission, validate the submitted parameters.
- If the submitted parameters are valid, process them.
- If the submitted parameters are invalid, show the form.
With a function-based structure, the code to accomplish this looks something
like:
if (array_key_exists('_submit_check',$_POST)) {
// If validate_form() returns errors, pass them to show_form()
if ($form_errors = validate_form()) {
show_form($form_errors);
} else {
// The submitted data is valid, so process it
process_form();
}
} else {
// The form wasn't submitted, so display
show_form();
}
The page either displays the form (possibly with error messages) or displays
the results of processing the form.
On other pages, particularly search pages, the logical flow goes like this
instead:
- If the request is a form submission, validate the submitted parameters.
- Display the form.
- If the request is a form submission, process the submitted parameters.
With a function-based structure, the code to accomplish this looks something
like:
// Check for errors if the form was submitted
$form_errors = array_key_exists('_submit_check',$_POST) ?
validate_form() : null;
// Always display the form
show_form($form_errors);
// Display results if the form was submitted
if (array_key_exists('_submit_check', $_POST)) {
process_form();
}
Displaying the form above the processing output is useful for pages where
users might want to adjust the form parameters based on the results. For
example, if a product search for toasters that cost between $150 and $300 reveals only two choices, a user can adjust the price range and resubmit the form for a
new search without going to a separate page.
5. Validate numbers with strval() and intval() or
floatval().
Usually, the ability to switch a variable smoothly between holding a string
or a number is a great convenience in your PHP programs. However, that makes
form validation a little harder. To check whether a submitted form parameter is a
valid integer, use strval() and intval() together like
this:
if ($_POST['age'] != strval(intval($_POST['age'])) {
$errors[] = 'Please enter a valid age.';
}
If $_POST['age'] isn't an integer, then intval() changes
its value to something else. Adding strval() to the mix ensures that
the comparison using the != operator doesn't do any silent,
behind-the-scenes conversion.
Similarly, to check whether a submitted form
parameter is a valid floating-point number, use floatval() instead of
intval():
if ($_POST['price'] != strval(floatval($_POST['price']))) {
$errors[] = 'Please enter a valid price.';
}
6. Entity-escape form data before printing it.
Printing data that comes from an external source (like form input) without
properly encoding it leaves you vulnerable to the common, devastating, and
embarrassing "cross-site scripting attack."
Pass external data through htmlentities() before printing it, like
this:
print "Your monkey's name is: " .
htmlentities($_POST['monkey_name']);
Read more about cross-site scripting at http://www.owasp.org/documentation/topten/a4.html.
7. Print form elements' defaults with helper functions.
Printing out appropriate HTML for individual form elements is boring and
repetitive. Fortunately, computers are quite good at boring and repetitive tasks.
Encapsulate logic for printing HTML form elements in functions. Then, call those
functions whenever you need to print a form element. Chapter 6 of Learning PHP 5
includes functions for a number of form elements. Here are a few samples:
// print a single-line text box
function input_text($element_name, $values) {
print '<input type="text" name="' . $element_name .'" value="';
print htmlentities($values[$element_name]) . '">';
}
//print a textarea
function input_textarea($element_name, $values) {
print '<textarea name="' . $element_name .'">';
print htmlentities($values[$element_name]) . '</textarea>';
}
//print a radio button or checkbox
function input_radiocheck($type, $element_name,
$values, $element_value) {
print '<input type="' . $type . '" name="' .
$element_name .'" value="' . $element_value . '" ';
if ($element_value == $values[$element_name]) {
print ' checked="checked"';
}
print '/>';
}
//print a submit button
function input_submit($element_name, $label) {
print '<input type="submit" name="' . $element_name .'" value="';
print htmlentities($label) .'"/>';
}
These functions are called like this:
print '<form method="POST" action=" . $_SERVER['PHP_SELF'] . '">';
print 'Name: '; input_text('name', $_POST);
print '<br/>';
print 'Description: ';
input_textarea('description', $_POST);
print '<br/>';
print 'Advanced?';
input_radiocheck('check','editor', $_POST, 'yes');
print '<br/>';
print 'Size: Big ';
input_radiocheck('radio','size', $_POST, 'big');
print ' Small ';
input_radiocheck('radio','size', $_POST, 'small');
print '<br/>';
input_submit('submit', 'Save');
The functions are easily extendable to add your own layout or support for
arbitrary attributes for each element.
8. Investigate HTML_QuickForm for advanced form processing.
For more advanced form handling, check out the PEAR module HTML_QuickForm. It
provides methods for the flexible and structured creation, validation, and display of
HTML forms. HTML_QuickForm frees you from doing the grunt work of displaying
defaults for form elements, encoding HTML entities, and duplicating validation
code. Its built-in layout engine is customizable, and you can integrate with
template engines like Smarty.
David Sklar
is an independent consultant in New York City, the author of O'Reilly's Learning PHP 5, and a coauthor of PHP Cookbook.
In June 2004, O'Reilly Media, Inc., released Learning PHP 5.
Sample Chapter 8, "Remembering Users with Cookies and Sessions," is available
free online.
You can also look at the Table of Contents, the
Index, and the full description of
the book.
For more information, or to order the book,
click here.
 |
Essential Reading
Building Tag Clouds in Perl and PHP
By JimBumgardner
Tag clouds are everywhere on the web these days. First popularized by the web sites Flickr, Technorati, and del.icio.us, these amorphous clumps of words now appear on a slew of web sites as visual evidence of their membership in the elite corps of "Web 2.0." This PDF analyzes what is and isn't a tag cloud, offers design tips for using them effectively, and then goes on to show how to collect tags and display them in the tag cloud format. Scripts are provided in Perl and PHP. Yes, some have said tag clouds are a fad. But as you will see, tag clouds, when used properly, have real merits. More importantly, the skills you learn in making your own tag clouds enable you to make other interesting kinds of interfaces that will outlast the mercurial fads of this year or the next.
Read Online--Safari
Search this book on Safari:
|
Return to the PHP DevCenter