Skip to main content.

Sunday, September 18, 2005

In this article, I'm re-creating the example from the Friendly Forms post using HTML_QuickForm (a PEAR package) and the Smarty template engine. I'm also looking into how to easily distribute PEAR with your application.

Some background

A while back I posted an article about a script I wrote to create friendly forms more easily. When I talk about "friendly forms", I'm talking about forms that get displayed again when some input is wrong. The fields are pre-filled with the submitted value again and visual indications (error messages and/or different styles) indicate which values needs to be corrected. Try the demo if you want to get an idea.

Sounded like a great start into friendly-fying the forms in the Nucleus admin area. The only problem is that my code required a lot PHP code mixed into the page HTML. This is not a good thing, so I was looking for something more flexible.

After reading some chapters about HTML_QuickForm and Smarty in the Essential PHP Tools: Modules, Extensions and Accelerators book, I decided to look into a rewrite.

Friendly Forms: HTML_QuickForm

The HTML_QuickForm package greatly simplifies creating forms that have validation rules. For a simple non-styled form that doesn't have custom validation rules, the code will look much like this:

require_once('HTML/QuickForm.php');

$form =& new HTML_QuickForm();

$form->addElement('text', 'name', 'Name');
$form->addElement('text', 'zipcode', 'Zipcode');
$form->addElement('text', 'number', 'Number');
$form->addElement('submit', 'send', 'Send');

$form->addRule('name', 
               'Would you please enter your name?', 
               'required');
$form->addRule('zipcode', 
               'Would you please enter your zipcode?',
               'required');
$form->addRule('number', 
               'Would you like to enter your house number?', 
               'required');
$form->addRule('zipcode', 
               'Format zipcode like <code>1234 AB</code>', 
               'regex', '/^[0-9]{4} ?[A-Za-z]{2}$/');

if ($form->validate())
{
  // save data
}
else
{
  $form->display();
}

The resulting output looks fine, although it would be much more interesting if we could style the output. The HTML spit out by HTML_QuickForm contains a table, where each cell has align and valign attributes. And older versions of the library even inserted font-tags. Yikes! We'll work on that later. First, a little info on installing PEAR.

Including PEAR with applications

If you're browsing the PEAR documentation looking for install instructions, you'll find out that they assume that you either are a server administrator or have shell access to your webserver. There is also a section about installing a local PEAR copy through FTP, however. All of these methods use the go-pear script, which prepares your PEAR installation to be managed through the command line pear command.

But what to do when you're developing a PEAR-dependant application and want to distribute it to millions of users, without having them go through the trouble of installing PEAR manually? You want to have it so your users only need to unzip a bunch of files and get going.

Some trial and error brought me to the conclusion that all you need to use HTML_Quickform are these files:

  • pear/PEAR.php
  • pear/HTML/Common.php
  • pear/HTML/QuickForm.php
  • pear/QuickForm/**

Still 445KB though... But webspace is cheap enough nowadays, is it not?

If you include all of these files in a pear/ directory, all you still need to do is to make sure the include statements in the PEAR code find the correct files. This is done by setting the include_path PHP variable at the start of your script:

ini_set('include_path', './pear/' . PATH_SEPARATOR . ini_get('include_path'));
require_once('HTML/QuickForm.php');

Customizing the output: Smarty

Back to the friendly form now. After reading the chapter about HTML_QuickForm in the Essential PHP Tools book, I was left with a bad feeling: there was no indication whatsoever that there was an ability to customize the HTML output generated by the library.

I almost gave up, but then I discovered about how HTML_QuickForm supports template renderers, one of them being HTML_QuickForm_Renderer_ArraySmarty, which uses the Smarty template engine. We're back in business!

Smarty is a powerful template engine. My form template looks much like this:

<form {$form.attributes}>
  {$form.hidden}

  {$form.name.label} {$form.name.html}
  <br />

  {$form.zipcode.label} {$form.zipcode.html}
  <br />

  {$form.number.label} {$form.number.html}
  <br />

  {$form.send.html}     

  {* display an overview of all form errors *}
  {foreach from=$form.errors item=error name=errorloop}
   {if $smarty.foreach.errorloop.first}<ul class="error">{/if}
   <li>{$error}</li>
   {if $smarty.foreach.errorloop.last}</ul>{/if}
  {/foreach}

</form>

Quite simple, don't you think?

In the code where the form is defined, the $form->display() needs to be replaced, though:

define('SMARTY_DIR', './smarty/');	
require_once(SMARTY_DIR . 'Smarty.class.php');
require_once('HTML/QuickForm/Renderer/ArraySmarty.php');	

$tpl =& new Smarty();
$tpl->template_dir = './templates';
$tpl->compile_dir  = './templates';

$renderer =& new HTML_QuickForm_Renderer_ArraySmarty($tpl);

$renderer->setRequiredTemplate(
 '{strip}
  <span class="
     {if $error}error{/if}
     {if $required} required{/if}
   ">
   {if $error}<img src="fout_ikoon.gif" width="11" height="11" 
   alt="Warning: {$error|strip_tags|escape}" /> {/if}
   {$label}
  </span>
  {/strip}'
);
$renderer->setErrorTemplate('{$html}');

$form->accept($renderer);
$tpl->assign('form', $renderer->toArray());

// render and display the template
$tpl->display('verify-sample.tpl');

The sample

You can see the complete sample here. It's almost identical to the non-QuickForm/non-Smarty version, except that I couldn't assign a class="error" part to the input-HTML fields.

You can also download the code (210KB). If you want to try this, you'll need to make sure to chmod the templates/ directory to 777, since Smarty will want to write a compiled template in there.

Comments

QuickForm is nice. You should take a look at Pear's HTML_Template_Flexy (there is a renderer for it on QuickForm also). Flexy is faster but still flexible as Smarty, although much smaller.

One thing that bothers me using QuickForm (even with renderers) is my inability to add a CSS class to a input form inside the template, and not in the PHP code. I wonder if there is a simple way to do this...

Posted by moraes at Thursday, October 06, 2005 17:00:44

Do you have an example showing QuickForm using Flexy?

Posted by Jatinder at Wednesday, November 23, 2005 13:55:59

Great article, thank you for contributing.
Concerning the way to add some PEAR packages to a shared host without any other access than FTP, which happens to me almost everytime, I do quite the same as you.
The only thing is that very often the host has already pear installed, but not up-to-date at all.
I do not know how the include process behaves when you have two pear distribs declared in your include path, so I'm used to rewrite completely the include_path :
ini_set('include_path','./'.PATH_SEPARATOR. './pear/');
And as a complement to your smarty example, you cas see two other ways to user QF and smarty in this slideshow :
http://davidmintz.org/prese...

One of these is quite interesting as it works in a dynamic way.

Posted by arnodmental at Friday, December 30, 2005 11:45:46

VDVVXV

Posted by mistry_bhaven at Tuesday, August 01, 2006 20:15:12

Add Comment

This item is closed, it's not possible to add new comments to it or to vote on it