Enforcing Object Types in PHP: Filtering Input Objects in PHP 4 - Building an object-base web page: unexpected results due to the lack of object type checking (
Page 3 of 4 )
Having written a few (X)HTML widget classes, building a page generator class is a no-brainer process. I just have to define some basic methods and make the class take the widget objects as incoming parameters, in order to generate the web page. So, that’s my theory. Now, take a look at how the page generator class is defined for creating web documents:
class PageGenerator{
var $output='';
var $title;
function PageGenerator($title='Default Page'){
$this->title=$title;
}
function doHeader(){
$this->output='<html><head><title>'.$this->title.'</title></head><body>';
}
// the type of input objects is not checked
function addHTMLElement($htmlElement){
$this->output.=$htmlElement->getHTML();
}
function doFooter(){
$this->output.='</body></html>';
}
function fetchHTML(){
return $this->output;
}
}
As you’ll surely agree, the above class is quite primitive, but extremely useful for demonstrating my theory. Notice the signature for the “addHTMLElement()” method, which is definitely the one that does the hardest work of all. As you can see, this method takes an object of type ‘HTMLElement”, then calls its “getHTML()” method, and finally appends the returned code to the class’ general output.
Of course, the big issue worth noting here is that this method isn’t checking the type of object passed as an rgument, which can lead to undesirable results if objects of the wrong type (or even another data structure) are passed as a parameter. Now, are you seeing what I’m pointing out when object type checking is simply skipped?
Now, I’ll translate the above theory into concrete code, in order to clarify what I explained before. Please study the following PHP snippet:
// spawn some HTML elements
$h1=&new Header1(array
('name'=>'header1','class'=>'headerclass'),'Content for H1
element goes here');
$div=&new Div(array('name'=>'div1','class'=>'divclass'),'Content
for Div element goes here');
$par=&new Paragraph(array
('name'=>'par1','class'=>'parclass'),'Content for Paragraph
element goes here');
$ul=&new UnorderedList(array
('name'=>'list1','class'=>'listclass'),array
('item1'=>'value1','item2'=>'value2','item3'=>'value3'));
// use 'PageGenerator' class
$pageGen=&new PageGenerator();
$pageGen->doHeader();
// add 'HTMLElement' objects
$pageGen->addHTMLElement($h1);
$pageGen->addHTMLElement($div);
$pageGen->addHTMLElement($par);
$pageGen->addHTMLElement($ul);
$pageGen->doFooter();
// display web page
echo $pageGen->fetchHTML();
As shown above, I’ve spawned some (X)HTML widget objects, which in turn are pushed into the “addHTMLElement()” method of the page generator class, in order to create and display a simple web page. Doing so, I quickly built a web document integrated by an H1 header, then a DIV and a paragraph, and finally an unordered list.
Here, all of the page generation process is performed with no problems, since the objects passed to the page generator class are the correct ones. However, look at the following example, which introduces a minor change to the previous script:
// spawn some HTML elements
$h1=&new Header1(array
('name'=>'header1','class'=>'headerclass'),'Content for H1
element goes here');
$div=&new Div(array('name'=>'div1','class'=>'divclass'),'Content
for Div element goes here');
$par=&new Paragraph(array
('name'=>'par1','class'=>'parclass'),'Content for Paragraph
element goes here');
// create a simple string and pass it to the class
$ul='This is not a HTML element object!';
// use 'PageGenerator' class
$pageGen=&new PageGenerator();
$pageGen->doHeader();
// add 'HTMLElement' objects
$pageGen->addHTMLElement($h1);
$pageGen->addHTMLElement($div);
$pageGen->addHTMLElement($par);
$pageGen->addHTMLElement($ul);
$pageGen->doFooter();
// display web page
echo $pageGen->fetchHTML();
When I run the above snippet, this is the output I get on my browser:
Fatal error: Call to a member function on a non-object in
path/to/file/
As you can see, in this case the PHP interpreter complains loudly because I’ve passed to the “addHTMLElement()” method a simple string with the value “This is not a HTML element object!”, which triggers a fatal error when trying to call the corresponding “getHTML()” method of “HTMLElement” objects.
Here, I’ve deliberately contaminated the input of the page generator class with wrong data, but actually this situation could happen under real conditions, with the same (or even worse) results that you just saw. So, what’s the simplest solution for this problem? In short, the class should first check the type of object passed in, before performing its tasks. This operation is known as “object type enforcement,” and certainly is quite easy to implement within a given class.
In order to fix object type issues, I’ll refactor the core “addHTMLElement()”method, so its class can verify whether the type of object being passed on is correct or not. This will prevent eventual problems related to code contamination.