HomePHP Page 2 - Enforcing Object Types in PHP: Filtering Input Objects in PHP 4
Enforcing object types in PHP 4: building (X)HTML widgets classes - PHP
When you are writing an object-based web application in PHP, you want to prevent your classes from being convoluted with input objects of the incorrect type. These input objects can cause the application to throw a fatal error. In this article, you will learn how to enforce object types in PHP 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.