Introduction
Programmers are often told not to reinvent the wheel, and that the best programmers borrow from others before they start to build something themselves. PHP, being primarily a web language, sees a lot of reinventing in regards to form display, processing and validation. However, there’s a great PEAR package that needs a little more exposure: HTML_QuickForm. It makes handling the rendering and display of forms, and more usefully, both client and server-side validation, quick and easy. This article will take you through the basics of that package. It assumes familiarity with HTML form elements, and reasonably basic PHP skills.
Installing HTML_QuickForm
The package has only two requirements: a version of PHP that is at least 4.2, and the HTML_Common package. At the time of writing, HTML_QuickForm 3.2.7 is the newest version of the package, and it requires HTML_Common 1.2.1. There are moves underfoot to rewrite both of these packages for PHP 5 (in the form of HTML_QuickForm2, and HTML_Common2), but as yet neither has been released.
You can check what PEAR packages are already installed by using pear list:
pear list Installed packages: =================== Package Version State Archive_Tar 1.1 stable Console_Getopt 1.2 stable DB 1.6.2 stable Date 1.4.6 stable HTTP 1.2.2 stable Image_Canvas 0.3.0 alpha Image_Color 1.0.2 stable Image_Graph 0.7.2 alpha Mail 1.1.3 stable Net_SMTP 1.2.6 stable Net_Socket 1.0.1 stable PEAR 1.3.2 stable Validate 0.6.3 beta XML_Parser 1.0.1 stable XML_RPC 1.1.0 stable
This machine doesn’t have either HTML_QuickForm or HTML_Common, so they’ll need to be installed.
pear install HTML_Common downloading HTML_Common-1.2.3.tgz ... Starting to download HTML_Common-1.2.3.tgz (4,746 bytes) .....done: 4,746 bytes install ok: HTML_Common 1.2.3 pear install HTML_QuickForm downloading HTML_QuickForm-3.2.7.tgz ... Starting to download HTML_QuickForm-3.2.7.tgz (102,475 bytes) ........................done: 102,475 bytes install ok: HTML_QuickForm 3.2.7
Displaying the form
The code required to display a form is simple. Let’s start with an example:
<?php require_once "HTML/QuickForm.php"; // tell PHP to include the QuickForm package $form = new HTML_QuickForm('register', 'post'); // instantiate the object $form->addElement('text', 'firstName', 'Enter first name'); // add a text element $form->addElement('password','password', 'Enter your password'); // add a password element $form->addElement('textarea','ta','Description'); // add a textarea element $form->addElement('submit','sb','Submit form'); // add a submit button element $form->display(); ?>
It should be fairly self-explanatory what this snippet does. Include the package, instantiate the object, then add a text form element (called firstName, with the text Enter your first name appearing next to it, and then add a password form element called password, with the text Enter your password next to it. Here’s what the resulting HTML looks like:
<form action="/phpbuilder/html_quickform11.php" method="post" name="register" id="register"> <div> <table border="0"> <tr> <td align="right" valign="top"><b>Enter first name</b></td> <td valign="top" align="left"> <input name="firstName" type="text" value="" /></td> </tr> <tr> <td align="right" valign="top"><b>Enter your password</b></td> <td valign="top" align="left"> <input name="password" type="password" value="" /></td> </tr> <tr> <td align="right" valign="top"><b>Description</b></td> <td valign="top" align="left"> <textarea name="ta"></textarea></td> </tr> <tr> <td align="right" valign="top"><b></b></td> <td valign="top" align="left"> <input name="sb" value="Submit form" type="submit" /></td> </tr> </table> </div> </form>
As you can see HTML_QuickForm allows you to get away with a lot less typing to get the same output, so even without all the other benefits, the abstraction will at least save you some time (although I wouldn’t recommend it for just this purpose!). It also produces (with a minor exception) markup that’s XHTML Strict-compliant (with the minor exception of the legacy form name attribute, which can be easily removed). The above example utilised a text, a textarea and a password element. Here’s a list of the other elements HTML_QuickForm can add, along with the HTML_QuickForm name, and the HTML equivalent. They’re all given straighforward names, so if you know the HTML term, you’ll know the term to use here.
element | HTML |
---|---|
button | <input type=”button” /> |
checkbox | <input type=”checkbox” /> |
file | <input type=”file” /> |
hidden | <input type=”hidden” /> |
image | <input type=”image” /> |
password | <input type=”password” /> |
radio | <input type=”radio” /> |
reset | <input type=”reset” /> |
select | <select>. The <option> elements can be loaded from either an array or a database. |
submit | <input type=”submit” /> |
text | <input type=”text” /> |
textarea | <textarea> |
xbutton | <button> |
There are also various custom element types. We’re not going to look at any examples in this tutorial, but they’re listed here for reference.
advcheckbox | An advanced checkbox type, allowing checkboxes to pass multiple values. |
autocomplete | A text field with autocomplete. It’s a normal text element, but at each keypress JavaScript is used to read an array and autocomplete if there’s anything matching. |
date | A group of elements for inputting dates and times |
group | Allows several elements to be grouped into a single new entity. |
header | Allows a heading to be added to the form. |
hiddenselect | A select element containing hidden elements for everything already selected with the methods setDefaults() or setConstants(). |
hierselect | A select element where choosing one item from the first select will dynamically populate a linked second select element. |
html | Used to be used for adding raw HTML to a form, it’s now deprecated. |
link | A link type field |
static | Static data |
Validating the data
As you’ve probably discovered, clicking on the submit button in our earlier example doesn’t yet do much. If you look at the form action attribute, you’ll notice that the same script is called. To make things easier for itself, HTML_QuickForm forms reference themselves, so the same script is responsible for generating the form, validating it, and processing it if successful. To make something happen, we’ll need to add logic to process the submitted form, as well as validate the data.
Validation is the bane of many developers, but HTML_QuickForm makes it really easy to validate both on the client-side and the server-side. It does so with the addRule() method. Then, to actually perform the validation, the validate() method is called. We’ll now only display the form if it hasn’t yet been validated (the code to process the form would be called at that point). All very simple! Here’s an example with two rules, one stating that the first name is a required field, and the other that the first name must only contain letters (and this excludes names with a dash, so you may not want to do this in a real application!):
<? require_once "HTML/QuickForm.php"; $form = new HTML_QuickForm('register', 'post'); $form->addElement('text', 'firstName', 'Enter first name'); $form->addElement('password','password', 'Enter your password'); $form->addElement('textarea','ta','Description'); $form->addElement('submit','sb','Submit form'); $form->addRule('firstName', 'Your name is required', 'required'); $form->addRule('firstName', 'Your name can only contain letters','lettersonly'); if ($form->validate()) { // processing code goes here. echo 'Success!'; } else { $form->display(); } ?>
Try and see what happens when you submit this form with invalid data, and then again with valid data. A red star indicates that the first name is a required field. If the data is entered incorrectly (either left out, or containing anything but letters) an appropriate error message is displayed, also in red.
The above example uses the required and lettersonly rules. Here’s a list of all the rules that can be applied:
rule | argument | description |
---|---|---|
alphanumeric | Can only contain alphanumeric characters (letters and numbers). | |
compare | Compares two values. | |
true (which applies a DNS check) | Must be a valid email (in syntax) (checks for a valid hostname if the argument is set to true). | |
filename | $regex | The filename of the uploaded file must match the regular expression in $regex. |
lettersonly | Can only contain letters. | |
maxfilesize | $maxsize | The filename of the uploaded file cannot be larger than $maxsize bytes. |
maxlength | $maxlength | Can be at most $maxlength characters in length. |
mimetype | $mimetype | MIME type of the uploaded file must either be of type $mimetype (if $mimetype is scalar), or match one of the elements in $mimetype (if it’s an array). |
minlength | $minlength | Must be at least $minlength in length. |
numeric | Must contain a valid integer or decimal number. | |
nonzero | Cannot be zero. | |
nopunctuation | Cannot contain any punctuation characters, which include: ( ) . / * ^ ? # ! @ $ % + = , ” ‘ > . | |
rangelength | $minlength,$maxlength | Must be inclusively between $minlength and $maxlength characters in length. |
regex | $regex | Must match the regular expression $regex. |
required | Cannot be blank | |
uploadedfile | Must contain a successfully uploaded file. |