HomePHP Page 4 - Enforcing Object Types in PHP: Using the PHP5 instanceof Operator
Extending the use of the “instanceof” operator: nesting (X)HTML widgets - PHP
This is the second installment of the series “Enforcing object types in PHP.” Welcome back. As you’ll surely know, this three-part series goes through the basic concepts of object type enforcement in PHP 4/PHP 5. It explores different approaches for checking types of objects to help you avoid possible code contamination when objects of incorrect type are inputted within PHP classes.
Right. You’ve seen the nice functionality of the “instanceof” operator for checking the types of incoming objects that are injected straight to the web page generator class. Now, I’ll go one step further and add a checking routine to both constructors and “getHTML()” methods of (X)HTML widget classes, so they can accept other widgets as an input parameter. Check the improved classes listed below:
class Div extends HTMLElement{ private $output='<div '; private $data; public function __construct($attributes=array(),$data){ if(!$data instanceof HTMLElement&&!is_string($data)){ throw new Exception('Invalid parameter type'); } parent::__construct($attributes); $this->data=$data; } // concrete implementation for 'getHTML()' method public function getHTML(){ foreach($this->attributes as $attribute=>$value){ $this->output.=$attribute.'="'.$value.'" '; } $this->output=substr_replace($this->output,'>',-1); $this->output.=($this->data instanceof HTMLElement)? $this->data->getHTML():$this->data; $this->output.='</div>'; return $this->output; } } class Header1 extends HTMLElement{ private $output='<h1 '; private $data; public function __construct($attributes=array(),$data){ if(!$data instanceof HTMLElement&&!is_string($data)){ throw new Exception('Invalid parameter type'); } parent::__construct($attributes); $this->data=$data; } // concrete implementation for 'getHTML()' method public function getHTML(){ foreach($this->attributes as $attribute=>$value){ $this->output.=$attribute.'="'.$value.'" '; } $this->output=substr_replace($this->output,'>',-1); $this->output.=($this->data instanceof HTMLElement)? $this->data->getHTML():$this->data; $this->output.='</h1>'; return $this->output; } } class Paragraph extends HTMLElement{ private $output='<p '; private $data; public function __construct($attributes=array(),$data){ if(!$data instanceof HTMLElement&&!is_string($data)){ throw new Exception('Invalid parameter type'); } parent::__construct($attributes); $this->data=$data; } // concrete implementation for 'getHTML()' method public function getHTML(){ foreach($this->attributes as $attribute=>$value){ $this->output.=$attribute.'="'.$value.'" '; } $this->output=substr_replace($this->output,'>',-1); $this->output.=($this->data instanceof HTMLElement)? $this->data->getHTML():$this->data; $this->output.='</p>'; return $this->output; } } class UnorderedList extends HTMLElement{ private $output='<ul '; private $items=array(); public function __construct($attributes=array(),$items=array ()){ parent::__construct($attributes); if(!is_array($items)){ throw new Exception('Invalid parameter for list items'); } $this->items=$items; } // concrete implementation for 'getHTML()' method public 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.=($item instanceof HTMLElement)?'<li>'.$item->getHTML ().'</li>':'<li>'.$item.'</li>'; } $this->output.='</ul>'; return $this->output; } }
As the above classes demonstrate, I refactored their constructors and “getHTML()” methods respectively, in order to allow nesting (X)HTML elements when the corresponding web page is generated. Notice the inclusion of the following conditional block in each class constructor:
if(!$data instanceof HTMLElement&&!is_string($data)){ throw new Exception('Invalid parameter type'); }
Here, what I’m actually doing is making sure that only string data and objects of the “HTMLElement” type are allowed as input parameters inside each class. Otherwise, an exception is thrown by the respective method, and incidentally the execution of the application is stopped. So that’s the checking process regarding input data. Now, take a look at the new signature for “getHTML()” methods, which also use the “instanceof” operator:
As you can see, in this case this operator is useful for taking advantage of polymorphic features inherent to (X)HTML widget classes. If the $data property is also a widget, then its “getHTML()” method is called appropriately, resulting in the display of nested web page elements. On the other hand, if it’s only a string, then it’s appended directly to the overall output of the current class.
At this point, hopefully you’ve understood the key points of using the PHP 5 “instanceof” operator, in order to make sure that certain objects belong to a specific type. As you’ve seen in this tutorial, enforcing object types in PHP 5 is really a straightforward task. It's a good time for you to get started using this method for filtering objects in your PHP applications.
To wrap up
It’s time to say goodbye, but only for a short while. In this second part of the series, you learned how to use the “instanceof” operator, available in PHP 5, in order to check the type of your input objects. However, the method that I showed you isn’t the only one. In the last tutorial, I’ll explain how to implement the nice “type hinting” feature, which also exists in PHP 5, as the last approach for enforcing types of objects. See you in the last part!