Enforcing Object Types in PHP: Filtering Input Objects in PHP 4 - Enforcing object types in PHP 4: building (X)HTML widgets classes (
Page 2 of 4 )
Culled from my own experience, I know that some topics are best understood by example, and that’s precisely the case when forcing object types in PHP 4. In order to demonstrate how you can filter input objects that eventually can mess up the beautifully-crafted code you wrote for your application, let me show you an example that can help you to understand the nature of the problem when objects of the wrong type are injected into client code.
First, I’ll define some useful (X)HTML widgets classes, aimed at rendering web page elements, and then create a web page generator class, which will accept these widgets for displaying the corresponding web document. My first example will begin with building a base “HTMLElement” class, and then continue by deriving some subclasses, all without including any object type checking routines, so you can see what happens when objects of an incorrect type are passed to this generator class.
Here are the (X)HTML widget classes I mentioned before:
// define base class 'HTMLElement'
class HTMLElement{
var $attributes;
function HTMLElement($attributes){
if(!is_array($attributes)){
trigger_error('Invalid type for (X)HTML
attributes',E_USER_ERROR);
}
$this->attributes=$attributes;
}
// abstract 'getHTML()' method
function getHTML(){
if(get_class($this)=='HTMLElement'||!is_subclass_of
($this,'HTMLElement')){
trigger_error('This method is abstract. It cannot be
called!',E_USER_ERROR);
}
}
}
// define concrete class 'Div' - extends 'HTMLElement'
class Div extends HTMLElement{
var $output='<div ';
var $data;
function Div($attributes=array(),$data){
parent::HTMLElement($attributes);
$this->data=$data;
}
// concrete implementation for 'getHTML()' method
function getHTML(){
foreach($this->attributes as $attribute=>$value){
$this->output.=$attribute.'="'.$value.'" ';
}
$this->output=substr_replace($this->output,'>',-1);
$this->output.=$this->data.'</div>';
return $this->output;
}
}
// define concrete class 'Header1' - extends 'HTMLElement'
class Header1 extends HTMLElement{
var $output='<h1 ';
var $data;
function Header1($attributes=array(),$data){
parent::HTMLElement($attributes);
$this->data=$data;
}
// concrete implementation for 'getHTML()' method
function getHTML(){
foreach($this->attributes as $attribute=>$value){
$this->output.=$attribute.'="'.$value.'" ';
}
$this->output=substr_replace($this->output,'>',-1);
$this->output.=$this->data.'</h1>';
return $this->output;
}
}
// define concrete class 'Paragraph' - extends 'HTMLElement'
class Paragraph extends HTMLElement{
var $output='<p ';
var $data;
function Paragraph($attributes=array(),$data){
parent::HTMLElement($attributes);
$this->data=$data;
}
// concrete implementation for 'getHTML()' method
function getHTML(){
foreach($this->attributes as $attribute=>$value){
$this->output.=$attribute.'="'.$value.'" ';
}
$this->output=substr_replace($this->output,'>',-1);
$this->output.=$this->data.'</p>';
return $this->output;
}
}
// define concrete class 'UnorderedList' - extends 'HTMLElement'
class UnorderedList extends HTMLElement{
var $output='<ul ';
var $items=array();
function __construct($attributes=array(),$items=array()){
parent::HTMLElement($attributes);
if(!is_array($items)){
trigger_error('Invalid parameter for list
items',E_USER_ERROR);
}
$this->items=$items;
}
// concrete implementation for 'getHTML()' method
function getHTML(){
foreach($this->attributes as $attribute=>$value){
$this->output.=$attribute.'="'.$value.'" ';
}
$this->output=substr_replace($this->output,'>',-1);
foreach($this->items as $item){
$this->output.='<li>'.$item.'</li>';
}
$this->output.='</ul>';
return $this->output;
}
}
Right, that’s it. As you can see, I’ve first defined a generic, base 'HTMLElement' class, and then derived some specific (X)HTML widgets, such as <h1>, <div>, <p> and <ul> elements. Notice how each of these elements provides a concrete implementation for the “getHTML()” method, which was originally defined as abstract in the pertinent base class. So, at this stage I created a well-structured hierarchy of (X)HTML classes, where their objects can be passed to a web page generator class, in order to construct programmatically web documents. Want to learn how this will be done? Fine, move on to the next section and keep on reading.