Extending HTML_QuickForm_Rule

HTML_QuickForm is a very popular PEAR library that eases form design for the web programmer.  It consists of three separate but equally important parts – form components, form renderers, and form validators.  The last of these three is the focus of this week’s tutorial.

Web programmers always have to be considerate of the security risks involved in web application design, and user input is one of the top priorities in application security.  Thankfully, HTML_QuickForm makes validating forms a simple process, using object-oriented prinicples of inheritence while unifying client and server-side validation. 

It does this through a base validation class called HTML_QuickForm_Rule, which contains several extensions out of the box for various validation types.  To extend HTML_QuickForm with our own custom validation, three steps are required:

  1. Add a child class with our validation that inherits HTML_QuickForm_Rule
  2. Register the child class in our form
  3. Add the rule to our form element

Step 1
For this example, we will use a simple validation rule – a zip code.  HTML_QuickForm_Rule is an abstract class that contains one public property called $name,  and three methods, listed as follows:

  1. validate() – handles our server-side validation
  2. setName() – sets the rule name if we want to register it in our form as an object
  3. getValidationScript() – handles our client-side validation

getValidationScript() is optional, but preferred if we want to unify both client and server-side validation in one class.  setName() is also optional, used if we create an instance of our HTML_QuickForm_Rule child class and need to dynamically set the name – this tutorial does not cover this particular situation.

So our child class looks like this (comments have been stripped for the sake of space):

require_once 'HTML/QuickForm/Rule.php';
class HTML_QuickForm_Rule_Zipcode extends HTML_QuickForm_Rule {
  var $zipRegex = '/^[0-9]{5}([\-][0-9]{4})?$/';
  function validate($value) {
    if(preg_match($this->zipRegex, $value)) {
      return true;
    }
    return false;
  }
  function getValidationScript($options = null) {
    return array(" var zipRegex = " . $this->zipRegex . ";\n", "{jsVar} != '' && !zipRegex.test({jsVar})");
  }
}

Our validation is for a 5-digit zip code, followed by an optional dash and additional 4 digits. Our regular expression is stored in a class property, $zipRegex, to make edits more sightly. We name our file Zipcode.php, and save it at HTML/QuickForm/Rule/Zipcode.php

Step 2
When we register our new rule, we do it during the building of our HTML_QuickForm object:

$form->registerRule('zip_code', null, 'HTML_QuickForm_Rule_Zipcode', 'HTML/QuickForm/Rule/Zipcode.php');

registerRule() takes the name of our rule, the type (which you may leave null if defining HTML_QuickForm_Rule specifics), the classname, and the file path from the calling script to the rule’s parent class. I bolded for emphasis because this is not documented well and will cause errors if not entered correctly!

Step 3
Adding the rule to the form element is the simple part:

$form->addRule('zip_code', 'Please enter a 5-digit zip code using numbers only.', 'zip_code', '', 'client');

Note both params 1 and 3 are ‘zip_code’ the first parameter is the form element’s name, and the third parameter is the rule name registered in step 2. The second parameter is the error message, the fourth parameter is extra rule data (if we were registering a different rule type other than our extension), and the fifth parameter is filled if we want client-side as well as server-side validation.

And that’s it!

It seems like a lot of work for one simple regex though, doesn’t it? But let’s look at what we’ve done:

  1. We’ve created a custom rule that can be reused in all our applications.
  2. We’ve kept our validation separate from our presentation, which is a good principle of OOP.
  3. We’ve added client side validation while barely touching any javascript (reason enough there!!!)

If you want to build upon a good component-based library for creating forms in your application, HTML_QuickForm is the way to go. And if you need security in your app (who doesn’t?!?), HTML_QuickForm_Rule is the way to achieve it.

  1. No Comments