Are you interested in expanding your knowledge of creational design patterns and learning how to work with director and builder objects in PHP 5? If your answer is yes, then I think you should start reading this article right now! Welcome to the concluding part of the series “How to Use Builder Objects in PHP 5.” This series leads you through the application of the builder pattern in PHP, and shows you how to use it with copious hands-on examples.
Before I proceed to creating the mentioned form director class that completes the schema imposed by the builder pattern, it's convenient to take a brief look at the classes that were defined in the previous article.
Doing so, you'll have a fresh idea of how each of the components that implements the builder mechanism look. Keeping in mind this relevant concept, I'll start by listing the first two classes involved into the creation process, that is the pair responsible for generating different form elements. The definitions for these classes are as follows:
// define abstract 'AbstractFormElement' class
abstract class AbstractFormElement{
abstract function getHTML();
}
// define concrete 'formElement' class
class FormElement extends AbstractFormElement{
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> element
else if(preg_match("/^(textarea|select)$/",$type)){
$openTag='<'.$type.' ';
$closeChar='>';
$closeTag='</'.$type.'>';
}
else{
throw new Exception('Invalid form element type');
}
if(!is_array($attributes)||count($attributes)<1){
throw new Exception('Invalid number of attributes for
<'.type.'> element');
}
// loop over element attribute
$elemAttributes='';
foreach($attributes as $attribute=>$value){
if(!$attribute||!$value){
throw new Exception('Invalid attribute or
value for <'.type.'> element');
}
$elemAttributes.=$attribute.'="'.$value.'" ';
}
// check for <select> option
$selOptions='';
if(count($options)>0){
foreach($options as $value=>$text){
if(!$value||!$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 overall (X)HTML output
public function getHTML(){<
return $this->html;
}
}
As shown above, these two classes represent the target element being created by the corresponding builder. In simple terms, the above "FormElement" class is tasked with rendering the different components that are found in typical online forms, such as input boxes, radio buttons, text areas, and so forth.
Now, and getting rid for a moment of the handy features that come with the "FormElement" class, I need you to pay strong attention again to the definition of the builder pattern: it is two objects, the director and the builder respectively, that play a relevant role within the creation of a third object.
In this case, since the target element is represented by all the form element objects eventually instantiated from the corresponding class, it's necessary to have at our disposal a builder class, which must be provided with the ability to create different form elements. At this moment, do you recall how all the objects that implement the builder pattern fit into the overall schema? I suppose you do.
To keep fresh in your mind the definition of the pertinent "FormBuilder" class that was created in the previous article, during the following section I'll be taking a quick look at it. Therefore, if you need to recall how the aforementioned form builder class looked originally, please read the next few lines.