PHP HTML_QUICKFORM2

QuickForm 2 is a PHP library which makes the development of complex and modern HTML forms easier and faster. It is the natural successor of QuickForm with a new revamped API, PHP5 support, new features and less bloat. Its development was started in 2007 by Alexey Borzov and Bertrand Mansion, and we are very close to a first beta release. I already use QuickForm 2 in production on a dozen of sites and since its code is almost fully unit tested, it is very stable.

In this post, I propose to create a simple contact form using QuickForm 2. It will have to contain some of the most useful form elements like text fields, submit buttons, etc. There won’t be any complex validation rules, since this is not our goal yet (although it might become the topic of another tutorial). We will use a filter to automatically trim our element values after they are submitted. And then, we will process our form.

Installing HTML_QuickForm2

QuickForm 2 is a PEAR package, so it can be easily installed using the following command from your command line:

pear install -f html_quickform2

This will also install the HTML_Common2 which is required by HTML_QuickForm2.

Form components

qf2-rocks

Before we get started with the code, there are some concepts you should know that will make your work with QuickForm 2 easier. More specifically, it is important to understand what makes a form :

  • Elements : Elements are the form widgets that receive input from the form users. In QuickForm 2, elements are text fields, textareas, select boxes, radio buttons, checkboxes, buttons, etc. In most cases, the elements are descendant of the HTML_QuickForm2_Element class. To build a form, basically, you just have to add elements to it.
  • Labels : Labels are what helps the users know what the input is expecting. Labels are usually placed in <label> tags although this can be changed by your form renderer. Checkable elements like radio buttons or checkboxes are also treated differently, their label is the text that is displayed next to each one of them. In QuickForm 2, an element can have multiple labels, this makes it easy to add descriptions and help text.
  • Required elements : Required elements are checked for contents when they are submitted. They are also marked as such, so the form renderer knows they should be treated differently because the user needs to know he has to fill them.
  • Groups and fieldsets : Elements can be grouped in generic containers. This helps organize your form logic and rendering. It is a very powerful feature of QuickForm 2 and is what makes working with it so pleasant (in my opinion). It is also a feature other form packages usually don’t have, last time I checked. Groups are descendant of the HTML_QuickForm2_Container class. By default, QuickForm 2 provides two containers : group and fieldset.
  • Submit elements : Submit elements need to be treated differently since they are usually display at the bottom of the form and they don’t need a label. They can be either right or left aligned. They trigger the submit event of the form which leads to the form validation and processing. By default, QuickForm 2 has a way to identify which form has been submitted, even if you have more than one form on a page. Submit elements can also be buttons and images.
  • Error messages : Errors are displayed once the form has be submitted and didn’t validate. QuickForm 2, thanks to its renderers flexibility, allows to group error messages together or display them next to the elements. Client side validation with javascript was added in version 0.5 and it works like HTML5 validation (but without the need for HTML5).

These are the basic parts that will usually compose your forms. QuickForm 2 has methods to deal with all of them in a flexible way as we will see now and in future tutorials.

Build the contact form

First thing, we’ll have to define our form object and specify how and where it is supposed to send its values when submitted.

$form = new HTML_QuickForm2('ContactForm', 'post', array(
    'action' => $_SERVER['PHP_SELF']
));

Notice that we used PHP_SELF as url for processing our form. It is usually a good habit to use an url that will process our form and then redirect to somewhere else once everything is done, using aheader('Location: /other-url'). This technique is called Post/Redirect/Get and is recommended with QuickForm 2.

Using PHP_SELF is fine because QuickForm 2 needs first to build the form in order to know what the elements and rules are. Most of the time, the form is built in PHP_SELF. The good news is that QuickForm 2 uses PHP_SELF by default so you actually don’t have to specify the third parameter if that’s all you need.

Now, let’s add some form elements.

// Let's start with a fieldset
$fs = $form->addFieldset('contact_us')->setLabel("Contact us");   // Add a title select box
$title = $fs->addSelect('title')
             ->setLabel("Title : ")
             ->loadOptions(array('' => "Select your title...", "Mr.", "Ms"));   // Add a name text field
$name = $fs->addText('name')->setLabel("Name : ");   // Add a comment textarea with 6 rows
$comment = $fs->addTextarea('comment', array('rows' => 6))
                      ->setLabel("Comments : ");   // Add the submit button to our form (outside of our fieldset)
$form->addSubmit('submit', array('value' => "Send us your comments"));

This is a lot like playing with HTML directly. You specify element attributes in the second parameter and they get added to your element tag. Shall we later enforce a maxlength for our text field, it would be as easy as :

$name->setAttribute('maxlength', 64);
$title->setAttribute('style', 'width:200px');

That’s because all our elements inherit from HTML_Common2 which does that for us.

Validation

All our fields should be required so we have to specify it.

$title->addRule("required", "Please specify your title");
$name->addRule("required", "Please specify your name");
$comment->addRule("required", "Please enter some comments");

Upon user submission, QuickForm 2 will check that these fields have been filled. But before we actually call the validate() method, let’s make sure that the submitted values are not only spaces or newlines. In order to achieve this, we’ll trim all our form values :

// Apply the trim() function recursively on all form children elements
$form->addRecursiveFilter('trim');

By default, QuickForm 2 uses what we call intrinsic validation on the server-side. It just means that user cannot submit non-existent values from your select box (it can be turned off). Let’s validate the form and output it to the browser :

if ($form->validate()) {
  echo "Success"; // Use a redirect here...
} else {
  echo $form;
}

Thanks to a hidden element, QuickForm 2 knows when the form needs to be validated and will not try to validate it if unnecessary.

The form can be output with a simple echo because like all other QuickForm 2 elements, the__toString() method is implemented.

Conclusion

If you just look at the code, you will see that we made a full featured contact form that has validation for required elements and select boxes, recursive trimming of values and that is reusable, in just a few lines. Note that we could even have added client-side validation with javascript without having to add a single line, but this will be talked about in another post…

In the future, I plan to talk more about rendering and styling forms using CSS and eventually a custom renderer. I also plan to post some nice tricks to make working with QuickForm 2 as efficient as possible and how to make your own elements with javascript. So, stay tuned

http://mansion.im/2011/getting-started-with-html_quickform2/

Leave a comment