Using Abstract Factory Classes in PHP 5 to Work with Online Forms

Any PHP developer who has worked with pattern-based programming in PHP for a while knows that the abstract factory pattern is useful for building classes that return (to client code) objects whose type depend on the content where they’re used. Welcome to the final installment of the series "Using abstract factory classes in PHP 5." If you’re interested in learning the key concepts of this helpful pattern, this three-part series will teach you how to apply it by developing numerous educational examples.

Surely, you’ll remember that in the course of the previous article, I demonstrated how to implement the logic that drives the abstract factory pattern to create diverse types of AJAX objects (commonly known as XML HTTP request objects), by defining two concrete factories.

Naturally, in accordance with the programmatic model established by the pattern in question, this pair of concrete factories would make sure that the correct type of HTTP requester objects would be returned to client code, depending on the context where they’d be used. More specifically speaking, the scenario that I just described demonstrates the remarkable functionality offered by the pattern when it comes to spawning objects that only work correctly in predefined environments.

So far, I think that all the practical examples that you learned during the two previous articles of the series should give you a more accurate idea not only of how this pattern works, but also how it can be applied in different situations that may be familiar to you.

However, I wouldn’t like to stop here, since the pattern’s capacity and functionality really deserve another close look. Therefore, in this last installment of the series, I’m going to show you how to use an abstract factory class to create distinct types of form objects, logically depending on the context where they will be utilized.

The idea not only sounds interesting, but it can provide you with a better understanding of how this handy pattern can be used in a real situation.

Having established the objectives for this final part of the series, let’s discover together how to use the abstract factory pattern in PHP 5 to generate web form elements. Let’s get started now!

{mospagebreak title=Defining an abstract form element factory class}

As I expressed in the introduction that you just read, I plan to define a group of concrete form element factories. These factories will be responsible for creating the correct types of form objects according to the context where these objects will be used.

Of course, before I proceed to defining this set of concrete factory classes, I must create an abstract form element factory class, in this way implementing the schema dictated by the referenced pattern.

As you’ll see in a brief moment, the abstract factory class that I’m going to define will set up a generic interface for building simple input and check boxes, as well as radio buttons. Nonetheless, after creating the abstract factory class, I’m going to derive three subclasses from it. These classes will come in handy for spawning "required" and "non-required" form objects, therefore establishing the respective contexts where these objects will be utilized.

Okay, having said that, here are the corresponding signatures for the abstract and concrete factories classes that I discussed previously. Please take some time to examine their respective signatures:

// define abstract ‘AbstractFormElementFactory’ class
abstract class AbstractFormElementFactory{
  
abstract public function createInputBox();
  
abstract public function createRadioButton();
  
abstract public function createCheckBox();
}

// define concrete ‘RequiredInputBoxFactory’ class
class RequiredFormElementFactory extends AbstractFormElementFactory{
  
private $context=’required’;
  
public function createInputBox(){
    
return new RequiredInputBox();
  
}
  
public function createRadioButton(){
    
return new RequiredRadioButton();
  
}
  
public function createCheckBox(){
    
return new RequiredCheckBox();
  
}
}

// define concrete ‘NormalInputBoxFactory’ class
class NormalFormElementFactory extends AbstractFormElementFactory{
  
private $content=’normal’;
  
public function createInputBox(){
    
return new NormalInputBox();
  
}
  
public function createRadioButton(){
    
return new NormalRadioButton();
  
}
  
public function createCheckBox(){
    
return new NormalCheckBox();
  
}
}

As illustrated above, the first abstract factory class defines a generic interface. This interface is convenient for creating web form objects, including check and input boxes, as well as radio buttons. Nevertheless, if you pay attention to the pertinent concrete factories, you’ll see that each one of them defines the context where the form objects will be utilized.

In this case in particular, the first factory will be responsible for creating web form objects that only work in a "required" context, while the second class will be capable of returning to client code, form objects that are functional in a "normal" (non-required) context. So far, the way that all the previous factory classes were defined is by far simple to understand, right?

Now, after having outlined generally the respective behaviors for each of the factory classes defined previously, it’s time to show the corresponding definitions for all the form element classes. These are tasked with generating input and check boxes, and radio buttons as well, in consonance with a predefined context.

As usual, to see how all these brand new classes will be created, click on the link shown below and keep reading.

{mospagebreak title=Creating context-driven form objects}

As you learned before, each one of the concrete factories defined previously exposes a "$context" property, which not surprisingly indicates the context in which different form objects must be created. So, taking into account this crucial feature that corresponds to the above mentioned classes, I’m going to define the first set of form elements classes. This set is tasked with rendering "required" input and form boxes, in addition to radio buttons.

Given that, take a look at the following code listing. It shows the respective definitions for these brand new classes. They are as follows:

// define ‘RequiredInputBox’ class
class RequiredInputBox{
  
public function display(){
    
return ‘<input type="text" required="true" size="25" />’;
 
}
}

// define ‘RequiredRadioButton’ class
class RequiredRadioButton{
  
public function display(){
    
return ‘<input type="radio" required="true" />’;
  
}
}

// define ‘RequiredCheckBox’ class
class RequiredCheckBox{
  
public function display(){
    
return ‘<input type="checkbox" required="true" />’;
  
}
}

As you can see, the logic implemented by the three classes shown above is extremely easy to grasp, since all that these classes do is generate the required markup for creating mandatory form elements.

Obviously, this condition is clearly demonstrated by adding to the markup in question, a "required" custom attribute, in this way indicating that all these form objects must work in a predefined "required" context.

Now that I’ve shown you the signatures for all the classes that render "required" web form elements, please have a look at the code for the following classes, which are responsible for displaying "normal" (non-required) radio buttons, as well as input and check boxes.

These classes look like this:

// define ‘NormalInputBox’ class
class NormalInputBox{
  
public function display(){
    
return ‘<input type="text" size="25" />’;
  
}
}

// define ‘NormalRadioButton’ class
class NormalRadioButton{
  
public function display(){
    
return ‘<input type="radio" />’;
  
}
}

// define ‘NormalCheckBox’ class
class NormalCheckBox{
  
public function display(){
    
return ‘<input type="checkbox" />’;
  
}
}

In this case, the above defined classes implement the logic necessary for creating non-required web form elements. Not surprisingly, this process is nearly identical to the one used for creating required form controls, but the "required" custom attribute has been completely removed from the pertinent markup.

All right, at this stage I’m sure that you should have a pretty good idea of how all the classes that I defined a few lines before can be put to work together to demonstrate the functionality offered by the abstract factory pattern.

Do you still need additional assistance to understand the topic? Okay, don’t worry, because in the last section of this article, I’m going to develop an illustrative example, where you’ll see how different form objects are instantiated by the corresponding concrete factories, by using only the context to which they belong.

Want to see how this process will be performed? Go ahead and read the next few lines. I’ll be there, waiting for you.

{mospagebreak title=Understanding how the abstract factory pattern works}

In order to understand more easily how diverse web form objects can be instantiated in accordance with a predefined context, below I set up an educational example. It shows in a step-by-step format how to display a few "required" and "normal" form elements, in consonance with a given instance of a factory class.

The source code that corresponds to the example in question is as follows:

try{
   
// instantiate ‘RequiredFormElementFactory’ object
   // (works in the ‘required’ context)
  
$factoryInstance=new RequiredFormElementFactory();
  
$reqInputBox=$factoryInstance->createInputBox();
  
$reqRadioButton=$factoryInstance->createRadioButton();
   
$reqCheckBox=$factoryInstance->createCheckBox();
  
// displays required form elements
  
echo ‘<form>’;
  
echo $reqInputBox->display();
  
echo $reqRadioButton->display();
  
echo $reqCheckBox->display();
  
echo ‘</form>’;
  
// instantiate ‘NormalFormElementFactory’ object
   // (works in the ‘normal’ context)
  
$factoryInstance=new NormalFormElementFactory();
  
$inputBox=$factoryInstance->createInputBox();
   
$radioButton=$factoryInstance->createRadioButton();
  
$checkBox=$factoryInstance->createCheckBox();
  
// displays normal form elements
  
echo ‘<form>’;
   
echo $inputBox->display();
  
echo $radioButton->display();
  
echo $checkBox->display();
  
echo ‘</form>’;
}
catch(Exception $e){
  
echo $e->getMessage();
  
exit();
}

Certainly, you must agree with me that the previous example is indeed demonstrative with reference to showing the functionality of the abstract factory pattern! As you can see, the above script first creates an instance of the "RequiredFormElementFactory" class, and then displays a simple web form, which contains a few "required " form elements. Logically, this is because this concrete factory makes sure that all the instantiated objects belongs to the "required" context.

Next, the example continues doing its thing and creates a new instance of the "NormalFormElementFactory" class, which not surprisingly is tasked with spawning form objects that belong to the "normal" context. Pretty good, right?

As you hopefully learned, in all cases, the concrete factories are completely responsible for making sure that the correct types of objects are returned to client code.

As with all of my articles on web development with PHP, I suggest that you experiment with using and modifying all the classes that I developed here, so you can acquire a better background on how this design pattern works.

Final thoughts

That’s all for the moment. In this three-part series, I provided you with a neat set of illustrative examples on how to build and use abstract factory classes with PHP 5.

Although it’s more probable that you’ll use only singletons and concrete factories during the development of object-oriented applications, there will be situations where you’ll need to use abstract factory classes to create objects that must exist only in a predefined context.

See you in the next PHP development tutorial!

Google+ Comments

Google+ Comments