PHP DevCenter
oreilly.comSafari Books Online.Conferences.

advertisement


Quick and Clean PHP Forms

by Adam Smith
09/13/2007

Introduction

As its name suggests, the PHP Extension and Application Repository (PEAR) library called HTML_QuickForm can be used to quickly and cleanly to produce validating HTML forms, relieving the developer of the tedium that often accompanies such tasks. HTML_QuickForm provides developers with a declarative approach to defining form fields and their associated validation rules and automatically generates the necessary HTML and JavaScript code needed to display the form accordingly. HTML_QuickForm also automatically validates submitted forms as indicated and allows developers to define a function that further handles valid submissions.

This tutorial presents a basic implementation of HTML_QuickForm to produce a common email contact form and explores ways to get the most from this powerful library.

When Is It Appropriate to Use HTML_QuickForm?

You may have inherited a legacy web site that is either entirely or mostly static and needs to have a dynamic form or two added to it. Or you may want to build a more dynamic site with a handful of forms that need to be processed flexibly. Maybe you are just mocking up some screens for a proposed web application and want a quick way to make those screens at least somewhat operational. The wide availability of PHP and its relative ease of use make it an ideal environment for adding dynamic functionality to sites that may be largely static otherwise, and libraries like HTML_QuickForm can make adding that functionality even easier.

Or maybe you are building a web application in a more comprehensive PHP framework but you need to add a form that doesn't fit well with the flow and design of the rest of the application. Or maybe because of your development philosophy, personal disposition, or level of experience, you are skeptical of highly structured web frameworks. You want to program your application from scratch your way, but you are open to taking advantage of third party libraries for solving specific challenges. In any of these cases, the HTML_QuickForm library can be used to create robust, validating forms that easily allow you to plug in your own code for processing valid form submissions.

An email contact form is a classic example of a form that gets tacked onto both static sites and complete web applications alike. This tutorial will describe how to use the PEAR HTML_QuickForm library to create a self-contained, pure PHP script that displays, validates, and processes a contact form, ultimately formatting the submitted data as an email message and sending it.

Finally, consider when it may be appropriate not to use a library like HTML_QuickForm. Complex web applications that are heavily form-driven, particularly if those forms perform primarily CRUD operations on a database, may benefit much more from a more complete, integrated web framework. CakePHP, is one such developer-friendly PHP framework inspired by Ruby on Rails.

Implementing a Contact Form with HTML_QuickForm

Previously through ONLamp, Keith Edmunds wrote a very nice tutorial called "Getting Started with PHP's HTML_QuickForm" that will be used here as a starting point. Following his example code closely, let's begin with this basic implementation of a contact form:

Example 1.

  
require_once "HTML/QuickForm.php";

$form = new HTML_QuickForm('contact_form', 'post');

$form->addElement('text',     'name',          'Name');
$form->addElement('textarea', 'address',       'Mailing Address');
$form->addElement('text',     'email_address', 'Email Address');
$form->addElement('text',     'home_phone',    'Home Phone');
$form->addElement('text',     'cell_phone',    'Cell Phone');
$form->addElement('text',     'subject',       'Subject');
$form->addElement('textarea', 'message',       'Message');   
$form->addElement('submit',   'submit',        'Submit');

$form->applyFilter('__ALL__', 'trim');

$form->addRule('name', 
               'Please enter your name.', 
               'required');
$form->addRule('email_address', 
               'Please enter your email address.', 
               'required');
$form->addRule('home_phone', 
               'Please enter your home phone number.', 
               'required');
                
if ($form->validate()) {
  $form->freeze();
  $form->process("process_data", false);
}
else {
  $form->display();
}

function process_data ($values) {
  require_once "emailHelper.php";
  emailValues($values);
}

The emailValues function will be described more fully later, but for now, it suffices to say that this is the helper function that formats and emails the validated form input.

As is, this code is simple, its intent is clear, and it demonstrates that like any good library, HTML_QuickForm provides a convenient way of performing a well defined task, in this case authoring and validating a typical contact form. HTML_QuickForm is so useful, you may find yourself using it often for similar forms, and as you integrate libraries like this into your personal set of tools, you may want to start to use it at a higher level, in a more idiosyncratic way that fits your needs and your personal programming style. To that end, let's begin exploring a few ways that this example could be further simplified, by introducing intelligent conventions and removing duplicated code.

First, it may be that often, and perhaps always, field names can be written in a conventional way such that they could then be used to programmatically generate a human-friendly form label when displaying the form. This approach could also be used to format the field name for the email message. In fact, the sample code already follows a typical approach of naming fields in complete words, separated by underscores, so a function can be written that replaces the underscores with spaces and converts the resulting string to title case, yielding something appropriate to use as a field label:

  
function createFieldLabel($field_name) {
  return ucwords(ereg_replace('[_]', ' ', $field_name));
}

For example, home_phone becomes "Home Phone." Many frameworks use a similar convention.

This function can now be used to simplify the creation of the form elements themselves. A simple multi-dimensional array mapping field names to HTML element types could be iterated over to call the function that generates the form elements:

  
$fields = array(
                array('name'          => 'text'    ),
                array('address'       => 'text'    ),
                array('email_address' => 'text'    ),
                array('home_phone'    => 'text'    ),
                array('cell_phone'    => 'text'    ),
                array('subject'       => 'text'    ),
                array('message'       => 'textarea'),
                array('submit'        => 'submit'  ),
               );
foreach ($fields as $key=>$value) {
  $form->addElement($value, $key, createFieldLabel($key));
}

Specifying form fields is simpler and the duplicate calls to addElement have been removed. This is a small optimization, but it's advisable to start as simply as possible. The true value of this approach can be judged more accurately as we expand its scope.

Adding validation rules points to a small amount of duplication when specifying field names. If a field name passed to addElement changes, its corresponding addRule constraint must also change. But, if a form element's validation rules can be added to the form at the same time as the element itself, the duplication and the potential for introducing that particular type of bug can be removed.

It is only at this point, when trying to introduce the field validations to the existing multi-dimensional array, that shortcomings of this approach become clear:

 
$fields = array('name'=>array('field_type'        =>'text',
                                 'validation_method' =>'required',
                                 'validation_message'=>'Please enter your name.',
                                ),
               ...
               );

The array syntax is becoming unwieldy, resulting in code that is more complicated, not less. The need to specify known array keys like field_type is also quite fragile. A better way is to start over, implement a real refactoring, and wrap both addElement and addRule calls in methods with explicit parameters:

function addRule($form, 
                 $field_name, 
                 $validation_method) {
  // this global variable seemed appropriate for now 
  global $default_messages; 
  if ($validation_method != '') {
    $validation_message = sprintf($default_messages[$validation_method], ereg_replace('[_]', ' ', $field_name));
    $form->addRule($field_name, 
                      $validation_message, 
                      $validation_method);
  }
}

function addElement($form, 
                    $field_name, 
                    $field_type, 
                    $validation_method='') {
  $form->addElement($field_type, 
                       $field_name, 
                       createFieldLabel($field_name));
  addRule($form, 
          $field_name, 
          $validation_method);
}

This new addElement function is not much more complicated to use than its original namesake that it is now wrapping, and it simultaneously calls a similar addRule wrapper function that simplifies adding validation rules. The parameters have also been ordered in a way that is perhaps more intuitive than the order dictated by the HTML_QuickForm API.

Additionally, default validation messages have been defined for the validation methods used, so that informative messages that also take advantage of the form field naming convention will be used automatically. The reasoning for this approach is that, apart from specifying the name of the field that failed validation, the message itself is more closely associated with a particular rule than any field to which that rule is applied. The following default messages illustrate this:

$default_messages = array ('required'=>'Please enter your %s.',
                           'email'   =>'Please enter a valid %s.'
                          );

Each message is associated with a particular rule in a format that can be processed by the PHP sprintf function, adding the appropriate field name in a human-friendly format based on the form field naming convention function defined above. These default messages avoid some duplication in specifying validation messages and ensure that those messages are rendered consistently.

Pages: 1, 2, 3

Next Pagearrow




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: