Enforcing Object Types in PHP: Using the PHP5 instanceof Operator

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.

Introduction

In accordance with the concepts that I discussed in the first part of this series, enforcing object types in PHP can sometimes be a crucial process. When it is avoided, either by lack of knowledge, incorrect programming assumptions, or simple laziness, you certainly may see undesirable effects during the execution of a specific Web application. Particularly when you’re programming with PHP 4, verifying the type of object which you’re working with can be easily achieved by using the “is_a()” function (although there are other methods). It definitely can be used for filtering input objects that need to be passed in as parameters to other PHP classes within the same application.

Nevertheless, PHP 4 does expose some weaknesses related to its Object Model that incidentally can demand writing additional code in order to implement certain features found in mature object-oriented languages. This fact has been well known for a long time by the PHP community. However, with the release of PHP 5, many of these highly desired features were added as part of the improved Object Model. They can help considerably in the development of tighter object-based code, allowing you to work with specific object features with minor hassles.

This is particularly noteworthy in the terrain of object type enforcement, since PHP 5 provides developers with at least two thorough methods for checking the type of objects during the execution of an Web application. These are the “instanceof” operator and the “type hinting” feature, respectively. Coming to the subject of this second tutorial, I’ll introduce the use of the “instanceof” operator in PHP 5, which, as you’ll see soon, can be really handy for determining whether the objects you’re using belong to a particular type.

The end result of this article hopefully will help you to expand your grounding in how to implement object type enforcement in PHP 5, by developing some illustrative, object-oriented examples. Are you interested in learning how to verify the type of your input objects in PHP 5? Right, let’s get started.

{mospagebreak title=Checking object types in PHP 5: what you shouldn’t do}

In order to demonstrate how you can force the type of your objects in PHP 5, I’ll use the set of (X)HTML widget classes that I showed you in the first article, in conjunction with a simple page generator class, in this case modified to work in a PHP 5 development environment.

My first example lists some (X)HTML widget classes derived from an abstract “HTMLElement” base class, which skip checking the type of input objects passed to them. Please have a look at the classes below:

// define abstract class ‘HTMLElement’
abstract class HTMLElement{
    protected $attributes;
    protected function __construct($attributes){
        if(!is_array($attributes)){
            throw new Exception(‘Invalid attribute type’);
        }
        $this->attributes=$attributes;
    }
    // abstract ‘getHTML()’ method
    abstract protected function getHTML();
}
// define concrete class ‘Div’ – extends HTMLElement
class Div extends HTMLElement{
    private $output='<div ‘;
    private $data;
    public function __construct($attributes=array(),$data){
        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.'</div>';
        return $this->output;
    }
}
// define concrete class ‘Header1′ – extends HTMLElement
class Header1 extends HTMLElement{
    private $output='<h1 ‘;
    private $data;
    public function __construct($attributes=array(),$data){
        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.'</h1>';
        return $this->output;
    }
}
// define concrete class ‘Paragraph’ – extends HTMLElement
class Paragraph extends HTMLElement{
    private $output='<p ‘;
    private $data;
    public function __construct($attributes=array(),$data){
        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.'</p>';
        return $this->output;
    }
}
// define concrete class ‘UnorderedList’ – extends HTMLElement
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.='<li>’.$item.'</li>';
        }
        $this->output.='</ul>';
        return $this->output;
    }
}

As you can see, the above (X)HTML widget classes are quite useful for generating specific elements of a web page, but I purposely wrote the code of each class in such a way that they aren’t capable of verifying  the validity of input parameters. As you probably realize, incoming arguments are directly passed to class constructors and assigned as properties. The question that comes up is: is there anything wrong with doing so? Yes, there is. Now, I’ll define my simple page generator class, and feed it with some of these widgets, so you can see how this class’ input is messed up with incorrect objects. Here’s the signature for the page generator class:

class PageGenerator{
    private $output=”;
    private $title;
    public function __construct($title=’Default Page’){
        $this->title=$title;
    }
    public function doHeader(){
        $this->output='<html><head><title>’.$this-
>title.'</title></head><body>';
    }
    public function addHTMLElement($htmlElement){
        $this->output.=$htmlElement->getHTML();
    }
    public function doFooter(){
        $this->output.='</body></html>';
    }
    public function fetchHTML(){
        return $this->output;
    }
}

Now, it’s time to instantiate a few (X)HTML widget objects, and pass them to the corresponding generator class, as shown in the example below:

try{
    // 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′));
    // instantiate page generator 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();
}
catch(Exception $e){
    echo $e->getMessage();
    exit();
}

After running the above PHP code, what you obtain as a result is a simple web page that includes some of the (X)HTML objects created before. In this situation, it’s easy to understand what would happen if, for some reason, the web page generator class received an incorrect object when its “addHTML()” method is called. Here, I recreate this conflictive condition by using a non-existing (X)HTML widget object. Again, take a look at the sample code below:

try{
    // 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′));
    // instantiate page generator class 
    $pageGen=new PageGenerator();
    $pageGen->doHeader();
    // add ‘HTMLElement’ objects
    $pageGen->addHTMLElement($fakeobj) //pass non-existing object
to this method
    $pageGen->addHTMLElement($div);
    $pageGen->addHTMLElement($par);
    $pageGen->addHTMLElement($ul);
    $pageGen->doFooter();
    // display web page
    echo $pageGen->fetchHTML();
}
catch(Exception $e){
    echo $e->getMessage();
    exit();
}

In this case, as the following line shows:

$pageGen->addHTMLElement($fakeobj) //pass non-existing object to
this method

a non-existing (X)HTML widget object is passed to the page generator class, which raises a fatal error:

Fatal error: Call to a member function on a non-object in
path/to/file

Right, that’s a direct punishment for not checking the type of objects being passed to the generator class, so be aware of this problem when coding your scripts. Luckily, there’s a simple solution for solving these issues, and here’s where the “instanceof” operator comes in very handy. If you want to see how this operator will be used, go ahead and read the next section.

{mospagebreak title=Forcing object types in PHP 5: using the “instanceof” operator}

As you’ll see, the “instanceof” operator is very simple to use. It takes two arguments for doing its business. The first one on the left is the object you want to check, while the second one, placed on the right, is the name of the class (or eventually an interface name) used for determining if the object in question is “an instance of” the pertinent class. Of course, I deliberately used the above terms, thus you can see how intuitive this operator is. Its basic syntax is as follows:

if (object instanceof class name){
    // do something useful
}

Now that you know how this operator is used in PHP 5, let’s redefine the corresponding web page generator class, in order to verify the type of objects passed to its “addHTMLElement()” method. Here’s the new signature for this class, which as I mentioned before, uses the “instanceof” operator:

class PageGenerator{
    private $output=”;
    private $title;
    public function __construct($title=’Default Page’){
        $this->title=$title;
    }
    public function doHeader(){
        $this->output='<html><head><title>’.$this-
>title.'</title></head><body>';
    }
    public function addHTMLElement($htmlElement){
        if(!$htmlElement instanceof HTMLElement){
            throw new Exception(‘Invalid (X)HTML element’);
        }
        $this->output.=$htmlElement->getHTML();
    }
    public function doFooter(){
        $this->output.='</body></html>';
    }
    public function fetchHTML(){
        return $this->output;
    }
}

Please notice in the above class how the “instanceof” operator is included inside the “addHTMLElement()” method, in order to make sure that all the objects passed in are instances of the “HTMLElement” class, defined earlier. Now, it’s possible to rebuild the web page you saw previously, in this case making sure that all the input objects pushed into the web page generator class are true (X)HTML widget objects. Here’s the corresponding example:

try{
    // 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’);
    $teststr=’This is not a HTML element’;
    // instantiate page generator class 
    $pageGen=new PageGenerator();
    $pageGen->doHeader();
    // add ‘HTMLElement’ objects
    $pageGen->addHTMLElement($teststr) //pass simple string to this method
    $pageGen->addHTMLElement($h1);
    $pageGen->addHTMLElement($div);
    $pageGen->addHTMLElement($par);
    $pageGen->doFooter();
    // display web page
    echo $pageGen->fetchHTML();
}
catch(Exception $e){
    echo $e->getMessage();
    exit();
}

As you can see in the above example, I passed a simple test string (not a “HTMLElement” object) in to the web page generator class, which will result in an exception thrown by the “addHTMLElement()” method, being caught for the appropriate “catch” block, as follows:

Invalid (X)HTML element

At this point, I used the “instanceof” operator, in order to determine the validity of input objects, which transform the above web page generator class into a much more efficient piece of code. I hope you realize the vital importance of filtering the input of your class methods by this operator, thus they can be shielded from incorrect data coming from outside.

Having illustrated the proper implementation of the “instanceof” operator within the web page generator class, there’s still one more thing to be done. Similar to the (X)HTML widget classes I wrote for PHP 4 in my previous article, I’d like to include this operator as part of their “getHTML()” method, in this way allowing the creation of web pages that render nested (X)HTML elements. Thus, let’s jump together into the next section, to see how this is done.

{mospagebreak title=Extending the use of the “instanceof” operator: nesting (X)HTML widgets}

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:

$this->output.=($this->data instanceof HTMLElement)?$this->data-
>getHTML():$this->data;

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!

[gp-comments width="770" linklove="off" ]

antalya escort bayan antalya escort bayan Antalya escort diyarbakir escort