Home arrow PHP arrow Page 2 - Enforcing Object Types in PHP: Using the PHP5 instanceof Operator

Checking object types in PHP 5: what you shouldn’t do - 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.

TABLE OF CONTENTS:
  1. Enforcing Object Types in PHP: Using the PHP5 instanceof Operator
  2. Checking object types in PHP 5: what you shouldn’t do
  3. Forcing object types in PHP 5: using the “instanceof” operator
  4. Extending the use of the “instanceof” operator: nesting (X)HTML widgets
By: Alejandro Gervasio
Rating: starstarstarstarstar / 10
February 22, 2006

print this article
SEARCH DEV SHED

TOOLS YOU CAN USE

advertisement

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.



 
 
>>> More PHP Articles          >>> More By Alejandro Gervasio
 

blog comments powered by Disqus
escort Bursa Bursa escort Antalya eskort
   

PHP ARTICLES

- Hackers Compromise PHP Sites to Launch Attac...
- Red Hat, Zend Form OpenShift PaaS Alliance
- PHP IDE News
- BCD, Zend Extend PHP Partnership
- PHP FAQ Highlight
- PHP Creator Didn't Set Out to Create a Langu...
- PHP Trends Revealed in Zend Study
- PHP: Best Methods for Running Scheduled Jobs
- PHP Array Functions: array_change_key_case
- PHP array_combine Function
- PHP array_chunk Function
- PHP Closures as View Helpers: Lazy-Loading F...
- Using PHP Closures as View Helpers
- PHP File and Operating System Program Execut...
- PHP: Effects of Wrapping Code in Class Const...

Developer Shed Affiliates

 


Dev Shed Tutorial Topics: