PHP Tutorial :: Forms (VIII)

PHP Example #72

A complete form application

The following example shows a complete form application that includes all the basic functions: firstly, show the form controls and default values, then validate input data, then if necessary show error warnings, together with the form controls and previous input values introduced by the user, and finally process the form if the input data is valid.

The first part of the source code consists of auxiliar functions that are used to print the controls of the form, allowing for simplification in the coding process. These functions are particularly handy because the different HTML controls require different algorithms for their codification. Note how PHP and HTML modes alternate in the source code; the structural table for containing the form is coded outside the domain of PHP, while each form control is printed via brief PHP calls to the auxiliary functions.

There are four main areas in the source code: the global scope (auxiliary functions, arrays for the menu options and the main logic for the form) and the three functions that control the form (show_form(), validate_form() and process_form().

Note how the validation of the input is strict for radio buttons and option lists, despite the fact that their default values cannot be altered by a regular user using a normal browser. But by using hacking techniques, a fake petition could be set for these apparently inflexible elements, so the validation function explicitly asks for the allowed values, not allowing strange values to be sent.

When the form is processed, htmlentities() ensures that no script that could be sent thru the text fields or the HTML controls values will be executed, by replacing the HTML tags with HTML entities that work like plain text. The nl2br() function turns PHP line breaks into HTML line breaks that will be correctly displayed in a web browser.

// Prints a text field
function input_text($element_name, $values) {
print '<input type="text" name="' . $element_name . '" value="';
print htmlentities($values[$element_name]) . '"/>';
// Prints a submit button
function input_submit($element_name, $label) {
print '<input type="submit" name="' . $element_name . '" value="';
print htmlentities($label) . '"/>';
// Prints a textarea
function input_textarea($element_name, $values) {
print '<textarea name="' . $element_name . '">';
print htmlentities($values[$element_name]) . '</textarea>';
// Prints a radio button or a 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 '/>';
// Prints a select menu
function input_select($element_name, $selected, $options, $multiple = false) {
// Prints the select label
print '<select name="' . $element_name;
// If multiple options are allowed, adds the multiple attribute
// and adds [] to the end of the label's name
if ($multiple) { print '[]" multiple="multiple'; }
print '">';
// Sets the list of selectable elements
$selected_options = array();
if ($multiple) {
foreach ($selected[$element_name] as $val) {
$selected_options[$val] = true;
} else {
$selected_options[$selected[$element_name]] = true;
// Prints the option labels
foreach ($options as $option => $label) {
print '<option value="' . htmlentities($option) . '"';
if (array_key_exists($option, $selected_options)) {
if ($selected_options[$option]) {
print ' selected="selected"';
print '>' . htmlentities($label) . '</option>';
print '</select>';
// Sets the options arrays in the select menus
// These are needed in display_form(), validate_form
// and process_form(), so they are defined in the global scope
$sweets = array('puff' => 'Sesame Seed Puff',
'square' => 'Coconut Milk Gelatin Square',
'cake' => 'Brown Sugar Cake',
'ricemeat' => 'Sweet Rice and Meat');
$main_dishes = array('cuke' => 'Braised Sea Cucumber',
'stomach' => "Sautered Pig's Stomach",
'tripe' => 'Sauteed Tripe with Wine Sauce',
'taro' => 'Stewed Pork with Taro',
'giblets' => 'Baked Giblets with Salt',
'abalone' => 'Abalone with Marrow and Duck Feet');
// The main logic of the form
// - If the form is sent, validate and then process or show it again
// - If it is not sent, show it
if (! array_key_exists('_submit_check', $_POST)) {
$_POST['_submit_check'] = 0;
if ($_POST['_submit_check']) {
// If validate_form() returns errors, pass them to show_form()
if ($form_errors = validate_form()) {
} else {
// The data sent is valid, then process it
} else {
// The form has not been sent, then show it
function show_form($errors = '') {
// If the form is sent, obtain the default values of the parameters sent
if ($_POST['_submit_check']) {
$defaults = $_POST;
} else {
// If not, set the own default values
$defaults = array('name' => '', 'size' => 'medium',
'sweet' => 'puff', 'main_dish' => array('cuke', 'stomach'),
'delivery' => 'yes', 'comments' => '');
// If errors were passed, put them in $error_text (with HTML codes)
if ($errors) {
$error_text = '<tr><td>You need to correct the following errors:';
$error_text = '</td><td><ul><li>';
$error_text .= implode('</li><li>', $errors);
$error_text .= '</li></ul></td></tr>';
} else {
// If there are no errors, then $error_text is empty
$error_text = '';
// Exit PHP mode to facilitate the visualization of all the HTML tags
<form method="post" action="<?php print $_SERVER['PHP_SELF']; ?>">
<?php print $error_text ?>
<tr><td>Your Name:</td>
<td><?php input_text('name', $defaults) ?></td></tr>
<td><?php input_radiocheck('radio', 'size', $defaults, 'small'); ?>
Small </br>
<?php input_radiocheck('radio', 'size', $defaults, 'medium'); ?>
Medium </br>
<?php input_radiocheck('radio', 'size', $defaults, 'large'); ?>
<tr><td>Pick one sweet item:</td>
<td><?php input_select('sweet', $defaults, $GLOBALS['sweets']); ?>
<tr><td>Pick two main dishes:</td>
<?php input_select('main_dish', $defaults, $GLOBALS['main_dishes'],
true) ?>
<tr><td>Do you want your order delivered?</td>
<td><?php input_radiocheck('checkbox', 'delivery', $defaults, 'yes'); ?> Yes
<tr><td>Enter any special instructions.<br/>
If you want your order delivered, put your address here:</td>
<td><?php input_textarea('comments', $defaults); ?></td></tr>
<tr><td colspan="2" align="center"><?php input_submit('save', 'Order'); ?>
<input type="hidden" name="_submit_check" value="1"/>
} // The end of show_form()
function validate_form() {
$errors = array();
// Name is required
if (! strlen(trim($_POST['name']))) {
$errors[] = 'Please enter your name.';
// Size is required
if (($_POST['size'] != 'small') && ($_POST['size'] != 'medium') &&
($_POST['size'] != 'large')) {
$errors[] = 'Please select a size.';
// Sweet is required
if (! array_key_exists($_POST['sweet'], $GLOBALS['sweets'])) {
$errors[] = 'Please select a valid sweet item.';
// Exactly two dishes are required
if (count($_POST['main_dish']) != 2) {
$errors[] = 'Please select exactly two main dishes.';
} else {
// We know that two dishes are selected, therefore,
// we make sure that both are valid
if (! (array_key_exists($_POST['main_dish'][0],
$GLOBALS['main_dishes']) &&
$GLOBALS['main_dishes']))) {
$errors[] = 'Please enter your address for delivery.';
// If delivery is activated, then the comments must contain something
if (($_POST['delivery'] == 'yes') &&
(! strlen(trim($_POST['comments'])))) {
$errors[] = 'Please enter your address for delivery.';
return $errors;
function process_form() {
// Seeks the full names of the sweet and the main dishes
// in the arrays $GLOBALS['sweets'] and $GLOBALS['main_dishes']
$sweet = $GLOBALS['sweets'][$_POST['sweet']];
$main_dish_1 = $GLOBALS['main_dishes'][$_POST['main_dish'][0]];
$main_dish_2 = $GLOBALS['main_dishes'][$_POST['main_dish'][1]];
if ($_POST['delivery'] == 'yes') {
$delivery = 'do';
} else {
$delivery = 'do not';
// Creates the text of the message
$message = 'Thank you for your order, ' . $_POST['name'] . ".\n" .
'You requested the ' . $_POST['size'] . ' size of ' . $sweet . ', ' .
$main_dish_1 . ' and ' . $main_dish_2 . ".\nYou " . $delivery .
" want delivery.\n";
if (strlen(trim($_POST['comments']))) {
$message .= 'Your comments: ' . $_POST['comments'];
// Sends the message to the cook
mail('', 'New Order', $message);
// Prints the message, but codifying any HTML entity
// <br/> tags and convert the new lines into <br/> tags
print nl2br(htmlentities($message));
Your Name:
Size: Small
Pick one sweet item:
Pick two main dishes:
Do you want your order delivered? Yes
Enter any special instructions.
If you want your order delivered, put your address here: