13th Jul 2005

Posted in

Blog :: Quickform Integration Example 1

My first experience in using php was upgrading old sites that had been written for PHP/FI (PHP v2 I think, originally stood for Personal Home Pages/Form Interpreter) to the new and improved PHP 3.  Coming from writing old school ASP/VBScript sites, PHP actually felt pretty good.  Pretty soon, though every server side web jockey (CGI/perl/ASP/JSP/whatever) starts looking for ways to simplify form generation.  Now I maintain that you ought to have to spend some time writing while loops that put the "selected" value in the option tag.  But once you've done this a hundred times you start looking for libraries.  In my case this was PHPLIB.

Now PHPLIB was pretty elite back in the day.  Even when I picked it up though, it was just about at the end of its life cycle; I ended up maintaining my own version that fixed a few bugs.  It did allow you to build a select box with one function call and slotted easily into the PHPLIB style templates.  With the creation of PEAR, however, PHPLIB lost steam (although some bits got ported to PEAR IIRC).  Now with PEAR as the official repository of PHP libraries with some degree of uniformity as to quality, code style, and integration, I decided to learn HTML_QuickForm.  QuickForm has a lot of interesting features: and makes it easy to generate forms from a database into a template.  Lately, since I've felt pretty comfortable with QuickForm and QuickForm_Controller I've started to extend QuickForm by writing my own rules and Form Types.  Two examples follow...

First a simple example.  QuickForm includes a "file" class that corresponds to a file upload control.  The file class has a function "MoveUploadedFile" that you can call while processing the form submission.  All very easy, but I wanted one step easier (plus I wanted to try a trivial extension).  I created a new rule by inheriting from the HTML_QuickForm_Rule class.  Code is as follows:

class HTML_QuickForm_UploadRule extends HTML_QuickForm_Rule
{   
	function validate($values, $path = null)
	{
		#realize this is pretty hacky.  Trying to figure out cleaner way to do this...
		if(is_array($path))
		{
			#callback should be a function that accepts 1 param, the full name of uploaded file eg "/var/foo/file1"
			$func =$path['callback'];
			$path = $path['path'];
		}
		if(!empty($values['name']))
		{
			$name = $values['name'];
			$ext =strrchr($name, '.'); 
			if( $ext !== False)
				$base = substr($name, 0, strrpos($name, '.'));
			else
			{
				$base =$name;
				$ext = '';
			}
			$success = move_uploaded_file( $values['tmp_name'], $path . '/' . $name);
			chmod($path . '/' . $name, 0666);          
			if(isset($func) and function_exists($func))
			{
				$func($path . '/' . $name);
			}
		}
		return(true);
	}
}

To use this rule in a form then, the following three lines of code suffice:

$this->form->registerRule('UploadRule', null, 'HTML_QuickForm_UploadRule', 'HTML_QuickForm_UploadRule.php');
$this->form->addElement('file', 'upload_file', 'Upload New File:');
$this->form->addRule('upload_file', 'Error message', 'UploadRule', '/var/www/html/foo','server',false,true);

You only need to register the rule once, of course, and after that usage is pretty transparent. Create a file element, add a rule to the element, and pass the directory you want the file to end up in as the "format" parameter. A little hackery is happening here, of course, as the format parameter in the docs is supposed to be a string, I accept an array that has a callback function. Is there a better way to do this? (I use it to pass an anonymous function that creates a thumbnail of uploaded pics.)

I recognize that this is pretty trivial stuff. So my next project was more ambitious... Using the script.aculo.us javascript library I created a drag n drop QuickForm ordering control. To be continued...

Update: Part two is up...

Posted on Jul 13th 2005, 10:44 PM