HomePHP Page 2 - Building a PHP 5 Form Processor: Coding the Form Generator Module
Creating online forms: defining a reusable class for rendering form elements - PHP
Most developers must deal with the job of developing robust data validation for forms on a regular basis. Nobody wants to write the same code over and over, so this article (the first of three in a series) will help you develop an extensible and reusable form validation package. By the end of the article, you will have all the relevant classes that integrate the generator module of the PHP form processor.
A good place to start coding the “generator” module is by defining a highly generic class, which can be capable of rendering programmatically form elements, and additionally integrating in a transparent way client-side validation routines. To meet all these requirements, I’ll begin defining the first class that composes the form processor, “formElement”. Its signature is shown below:
class formElement{ private $html=''; public function __construct($type='text',$attributes=array ('name'=>'default'),$options=array()){ // check for <input> elements if(preg_match("/^ (text|radio|checkbox|password|hidden|submit|reset|button|image| file)$/",$type)){ $openTag='<input type="'.$type.'" '; $closeChar=' '; $closeTag='/>'; } // check for <textarea> and <select> elements else if(preg_match("/^(textarea|select)$/",$type)){ $openTag='<'.$type.' '; $closeChar='>'; $closeTag='</'.$type.'>'; } else{ throw new Exception('Invalid element type'); } if(!is_array($attributes)||count($attributes)<1){ throw new Exception('Invalid number of attributes for <'.type.'> element'); } // loop over element attributes $elemAttributes=''; foreach($attributes as $attribute=>$value){ if(empty($attribute)||empty($value)){ throw new Exception('Invalid attribute or value for <'.type.'> element'); } // check for 'required' attribute - add client-side validation $attribute=='required'?JSGenerator::addValidation ($attributes ['name'],$value):$elemAttributes.=$attribute.'="'.$value.'" '; } // check for <select> options $selOptions=''; if(count($options)>0){ foreach($options as $value=>$text){ if(empty($value)||empty($text)){ throw new Exception('Invalid value or text for <'.type.'> element'); } $selOptions.='<option value="'.$value.'">'.$text.'</option>'; } } // build form element(X)HTML output $this->html.=$openTag.trim ($elemAttributes).$closeChar.$selOptions.$closeTag; } // return complete (X)HTML public function getHTML(){ return $this->html; } }
Despite the seemingly complex structure of the above class, its rationale is fairly simple, so fear not. Essentially, what the class does is render programmatically form elements, according to the incoming parameters passed to its constructor. As you can see, this method accepts three arguments: first, the name of the element being rendered; second, an array containing the attributes of that element; and finally, an optional $options array, which will only be used to build the set of <option> tags, when a select box needs to be displayed.
Of course, the constructor does most of the hard work, since it takes care of generating dynamically the required (X)HTML markup, in accordance with the type of form element entered as argument. Internally, this method will create the corresponding code for each form control and append it to the overall output, represented through the $this->html property.
So far, the logic behind the class is fairly clear and shouldn’t be difficult for you to understand. According to the checking process performed by a few regular expressions, the class will construct a specific form element, by adding the pertinent attributes passed in as class parameters. However, as I said right at the beginning of this tutorial, my intention was to provide the “generator” module with some client-side validation features. With reference to this, take a look at the following piece of code:
In short, what this line does is check for a “required” attribute, as part of the $attributes array. If this attribute is found, then a JavaScript checking snippet will be created on the fly by the “addValidation()” method, which, as you can see, belongs to the “JSGenerator” class. Are you wondering why I complicated the application by aggregating yet another class? Well, I decided to keep all the client-side validation routines encapsulated within a specific class, responsible for generating all the required JavaScript code.
As you can see, the methods of the “JSGenerator” class are used out of the object context -- notice the use of the resolution scope operator (::) –- and originally this class was defined as abstract, so I didn't have to concern myself too much with dealing with object instantiation. If this sounds rather confusing to you, don’t worry. In a few moments I’ll illustrate the functionality of this class.
Now, by returning to the “formElement” class, the remaining code speaks for itself. Note the definition of the “getHTML()” method, handy for fetching the (X)HTML markup of each form element:
public function getHTML(){ return $this->html; }
Hopefully you now understand how the “formElement” class works, so the next step in building the module for constructing forms will be showing the definition for the abstract “JSGenerator” class. All you have to do is scroll down the page and keep reading.