PHP DevCenter
oreilly.comSafari Books Online.Conferences.

advertisement


PHP Form Handling

by David Sklar,author of Learning PHP 5
08/26/2004
Add Tag Clouds to Your Site

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.

Building Tag Clouds in Perl and PHP

Essential Reading

Building Tag Clouds in Perl and PHP
By Jim Bumgardner

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:
 

Code Fragments only

Return to the PHP DevCenter


Valuable Online Certification Training

Online Certification for Your Career
Earn a Certificate for Professional Development from the University of Illinois Office of Continuing Education upon completion of each online certificate program.

PHP/SQL Programming Certificate — The PHP/SQL Programming Certificate series is comprised of four courses covering beginning to advanced PHP programming, beginning to advanced database programming using the SQL language, database theory, and integrated Web 2.0 programming using PHP and SQL on the Unix/Linux mySQL platform.

Enroll today!


Sponsored by: