PHP DevCenter

oreilly.comSafari Books Online.Conferences.

We've expanded our LAMP news coverage and improved our search! Search for all things LAMP across O'Reilly!

Search
Search Tips

advertisement

Listen Print Discuss Subscribe to PHP Subscribe to Newsletters

Getting Started with PHP's HTML_QuickForm
Pages: 1, 2

Adding Rules and Filters

In the simplest case, I wanted to ensure that the user really had entered a name before clicking the Submit button. To accomplish this, I called an addRule method of the form:

$form->addRule('txtName', 'Please enter your name', 'required');

The first argument is the name of the element to apply the rule to, the second is the error text to display if the rule fails, and the third is the type of rule to apply. This will require a value for txtName; it must not be blank. When the form displays, it will indicate that this is a required field. By default, a red asterisk will appear next to the field that refers to a note at the foot of the form. If txtName is blank, the validate method call will return false. This in turn will cause the form to redisplay, but now the error text (the second parameter to the addRule method) will display above the field that failed the validation.

By adding that one line of code, we can show the user which fields are mandatory, we can check that the user has filled them in, and we can provide feedback to the user in the event that they have not filled them all in. There are other built-in rules, including: maxlength, minlength, rangelength, email, regex, lettersonly, alphanumeric, numeric, nopunctuation, nonzero, and compare.

Suppose, however, that the user merely inserts a space in the txtName field. The validation will still pass because the field is not blank, but this is hardly what we want. There are other rules we could use -- for example, the regex rule checks the input against a regular expression, but that is complex way to solve a simple problem.

A better way approach is to use filters. A filter can be either the name of a user-supplied function or the name of a PHP built-in function. QuickForm will send the contents of the text field to this function before validation. In this case, the PHP function trim does precisely what we want by removing all leading and trailing spaces. Here it is in action:

$form->addRule('txtName', 'Please enter your name', 'required');
$form->applyFilter('txtName', 'trim');

The applyFilter method takes two arguments: the name of the element to apply the filter to, and the name of the filter, as described above. The element name can be the pseudo-element __ALL__, which, as you might expect, applies that filter to all elements.

User-Defined Rules

One of the elements on the form I designed was a checkbox that indicated whether the person wanted to subscribe to a mailing list. The validation required here is not so simple: the EmailAddress field should contain either a valid email address or nothing, but if the user has checked the MailingList checkbox, the EmailAddress field must not be blank.

We can achieve this with a different built-in rule in conjunction with a user-defined validation rule, as follows (see Example 1).

There's quite a lot extra here. First, I've added a couple of new elements: a text box for the user's email address and an advcheckbox for requesting a newsletter. The advcheckbox is a special HTML_QuickForm element. The problem with an ordinary checkbox is that it returns no value at all if left unchecked, making it more difficult to check in code; however, the advanced checkbox will always return a value, either TRUE or FALSE, as appropriate.

I've added a filter rule to remove leading and trailing spaces from all data entered. There are two element-specific rules: one to ensure that the user has entered a name, and the other, email, to ensure that any email address entered matches a valid format. If the email address is blank, the validation check will still pass; if an email address was required here, then a second rule, required, would also apply to the field. As it stands, the validation routine will only check that the format of the email address is legal. By specifying an additional parameter, the validation routine can also check whether the address given really exists.

Finally, we have a new method, addFormRule. This takes a single argument, the name of a user-written function that will help validate the form. This function, newcontact_validate, takes a single parameter in the form of an associative array consisting of element-name=>element-value pairs. This function returns either TRUE, indicating that validation has passed, or an associative array of invalid-element-name=>error-message pairs.

In this particular example, we only check that the user has supplied an email address if they have elected to receive a newsletter. However, the format of this function is generic enough to perform more complex validations. In the example shown, we first define an array in which to store any errors we find. We then carry out the checks, adding an element name and error message to the errors array for each validation error found. At the end of the function, we check the errors array and either return it if there are errors, or return true if everything validated. Any errors returned by the addFormRule function display in the same way as built-in validation rule failures.

Default Values

My form was almost complete. It worked well for entering details of new contacts, but I also wanted to use it to edit details of existing contacts. I needed a way to populate the fields with existing data. To accomplish this, I used the setDefaults method (see Example 2).

There are a few changes here, starting with the definition of some user data in the array $user. I'd normally retrieve this from a database, but for clarity I have hard-coded it here. The form definition resembles the previous version, but I have changed the element names to match the column names in my database. For example, txtName has become simply name. There is also a new element, hidden. As the name implies, this is a hidden element on the form. In this case, it stores the key field in the database to use in the resulting SQL UPDATE statement.

The final change is the setDefaults method. This takes a single argument, an associative array of element-name=>default-value pairs. Using the same name for both the database fields and the element names on the form greatly simplifies the population of default values and the later building of the SQL UPDATE statement. Any element that does not appear in the array passed with setDefaults retains its default (typically blank) value, so the same code can both create contacts (passing an empty defaults array) and edit contacts.

Conclusion

I now have a form which is in daily use. It consists of pure PHP code with none of the lack of clarity which can arise from mixing PHP and HTML code in the same file. My users use the same code both to create and edit contacts, which makes the application more consistent in its appearance and easier to maintain. All of the input fields are validated with very little code, and users receive good feedback if any of the validations fail.

You can find out more about PEAR at the PEAR web site and from the online PEAR manual. In this article, I have only scratched the surface of what can be achieved by PEAR's HTML_QuickForm classes. There's a lot more power available there. With the addition of templates, the resulting forms can look very professional -- but perhaps that is a subject for another time.

Keith Edmunds


Return to the PHP DevCenter


Have a question on Keith's code or a tip for new QuickForm users? Let us know here.
You must be logged in to the O'Reilly Network to post a talkback.
Post Comment
Full Threads Oldest First

Showing messages 1 through 10 of 10.

  • addFormRule callback
    2006-12-05 17:52:06  hemoglobina [Reply | View]

    If you are working with HTML_QuickForm from inside another function, callbacks do not work in the same way. I mean calling:
    $form->addFormRule( "newcontact_validate" );
    won't work due to scope issues.
    Does anyone know how to setup the callback from inside another class?
    At first I thought about doing it like this:
    $form->addFormRule( "$this->newcontact_validate" );
    but it did not work... I'm lost on this one.
    Thanks!
    • addFormRule callback
      2007-04-28 05:07:04  rzygler [Reply | View]

      To setup a callback from inside another class, you need to make the form a global var. So, in the calling class, you would start it with:

      global $form

      and then create the form from there. Then in the callback class method, you again use:

      global $form

      and you can reference the methods/elements of the form.
  • MySQL Table to PHP Array
    2006-02-12 13:06:35  jgbutler [Reply | View]

    I'm sure there's a simple way to do this, but I'm such a newbie I can't figure it out...

    I'm enjoying making my first HTML_QuickForm form, but I'm having trouble populating an array to use with $form->addElement('select'). I tried using the following code to pull data from a simple, 2-field MySQL table and insert it into an array named $genres, but all I get is the very first row of data. Can you clue me in as to how to get the other rows to cooperate?

    Thanks!

    mysql_select_db($database_tifrl, $tifrl);
    $query_rsGenre = "SELECT * FROM genre";
    $rsGenre = mysql_query($query_rsGenre) or die('Query failed: ' . mysql_error());
    $ar_genre = mysql_fetch_array($rsGenre, MYSQL_ASSOC);
    $genres = array ($ar_genre['genreID'] => $ar_genre['category']);
  • HTML_QuickForm references
    2005-10-21 10:15:40  Lucius_Agrippa [Reply | View]

    http://s-hbox.hopto.org/web_development/php/PEAR/HTML_Quickform/
  • Feedback
    2005-09-23 03:11:05  Lordspace [Reply | View]

    Here is a modified version of the example1

    it seems you can't addRule() in validation method to set up a rule that validates email address.


    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
    <html>
    <head>
    <meta http-equiv="Content-Type" content="text/html"
    charset="UTF-8">
    <title>Testing PEAR HTML_QuickForm</title>
    </head>
    <body>

    <?php
    require_once "HTML/QuickForm.php";

    $form = new HTML_QuickForm('frmTest', 'get');

    $form->addElement('header', 'hdrQuickformtest',
    'QuickForm Example 1');
    $form->addElement('text', 'txtName',
    'What is your name?');

    $form->addElement('text', 'txtEmail',
    'What is your email?');

    $form->addElement('advcheckbox', 'chkNewsletter',
    'Receive newsletter?');

    $form->addElement('reset', 'btnClear',
    'Clear');

    $form->addElement('submit', 'btnSubmit',
    'Submit');

    $form->addRule( 'txtName', "Please enter your name", "required" );
    $form->addFormRule( "newcontact_validate" );
    $form->applyFilter( '__ALL__', 'trim' );

    if ( @$_REQUEST[ 'chkNewsletter' ] )
    $form->addRule( 'txtEmail', "Please enter your email", "email" );

    if ($form->validate()) {
    # If the form validates, freeze and process the data
    $form->freeze();
    $form->process("process_data", false);
    }
    else {
    $form->display();
    }

    function process_data ($values)
    {
    echo "
    ";

    foreach ($values as $key=>$value) {
    echo $key."=".$value."
    ";
    }

    echo "
    ";
    }

    // when a checkbox is selected validate email address otherwise no
    function newcontact_validate( $fields )
    {
    # Set up array to store any errors
    $errors = array();

    # Carry out validation checks
    if ("1" == $fields['chkNewsletter']) {
    if (empty($fields['txtEmail'])) {
    $errors['txtEmail'] =
    "Please enter an email address for the newsletter";
    }
    }

    # Return the errors if we have any, or TRUE if not
    if (empty($errors)) {
    return TRUE;
    }
    else {
    return $errors;
    }
    }

    ?>
    </body>
    </html>

    Svetoslav
    http://devquickref.com
  • escaping from html does not work fine.
    2005-02-03 07:11:42  yasheshb [Reply | View]

    i'm using mozilla 1.7.3 and when i try to display the first example (saved it on my local box as ex1.html) it did not recognize the end tags for php
    ( and it takes the end tag of $form-> as the php ending tag instead of ?> ).

    • escaping from html does not work fine.
      2006-09-05 13:57:54  Jabbaugh [Reply | View]

      PHP is a server side language. This means that you will need to have php installed on your local machine as well as a web server. Additionally, you will need to save the file as "ex1.php". An html file will be interpreted as client side code. This means it will show all of your code to whoever looks at it as well as doing absolutely nothing.

      I hope this helps.

      Jim
  • Pretty Cool, but...
    2004-08-28 11:24:54  lukasn [Reply | View]

    What would be the best way of integrating HTML_QuickForm with a template engine like Smarty?
    • Pretty Cool, but...
      2005-01-18 14:46:04  aalex [Reply | View]

      You should use phpsavant.com instead. It's much lighter and you can access all your PHP variables and functions in the template !!
    • Pretty Cool, but...
      2004-10-31 15:05:16  superbenk [Reply | View]

      It's not too hard. Once you instantiate Smarty before the form, you output the form using Pear's Smarty rendering interface. You simply replace the $form->display(); line with something like the following:

      $renderer =& new HTML_QuickForm_Renderer_ArraySmarty($smarty);
      $form->accept($renderer);
      $smarty->assign('new', $renderer->toArray());
      $smarty->display('formtemplate.tpl');


Tagged Articles

Post to del.icio.us

This article has been tagged:

php

Articles that share the tag php:

Understanding MVC in PHP (477 tags)

The PHP Scalability Myth (123 tags)

The Dynamic Duo of PEAR::DB and Smarty (53 tags)

PHP Form Handling (43 tags)

Very Dynamic Web Interfaces (39 tags)

View All

pear

Articles that share the tag pear:

The Dynamic Duo of PEAR::DB and Smarty (37 tags)

Programming eBay Web Services with PHP 5 and Services_Ebay (12 tags)

Three-Tier Development with PHP 5 (6 tags)

PHP's PEAR on Mac OS X (6 tags)

Caching PHP Programs with PEAR (6 tags)

View All

form

Articles that share the tag form:

PHP Form Handling (4 tags)

Getting Started with PHP's HTML_QuickForm (2 tags)

View All

Sponsored Resources

  • Inside Lightroom
Advertisement

Sponsored by:

O'Reilly Media

©2009, O'Reilly Media, Inc.
(707) 827-7000 / (800) 998-9938
All trademarks and registered trademarks appearing on oreilly.com are the property of their respective owners.
About O'Reilly
Academic Solutions
Authors
Contacts
Customer Service
Jobs
Newsletters
O'Reilly Labs
Press Room
Privacy Policy
RSS Feeds
Terms of Service
User Groups
Writing for O'Reilly
Content Archive
Business Technology
Computer Technology
Google
Microsoft
Mobile
Network
Operating System
Digital Photography
Programming
Software
Web
Web Design
More O'Reilly Sites
O'Reilly Radar
Ignite
Tools of Change for Publishing
Digital Media
Inside iPhone
O'Reilly FYI
makezine.com
craftzine.com
hackszine.com
perl.com
xml.com

Partner Sites
InsideRIA
java.net
O'Reilly Insights on Forbes.com