Iterator Sample Code

Iterator: to wrap the looping routine through a collection of objects.

__iteratoruml.gif
Figure 1. Class diagram for the Iterator pattern

Iterator

Date:
12 Jan 2009

We will use this pattern when we need a routine to loop through a collection of objects, these collections can be anything; an array of pure objects, resultsets from a database, etc. but we'll always need to know if next element exists and be able to retrieve it.
So, we have (See Figure 1):

  • An interface that model the behaviour
  • A class that will implements this behaviour, and there we can have all the iterators that we want: SQLIterator, FileIterator, AnythingIterator.
All we need to do is call while($iterator->hasNext()) and deal with the next item with $iterator->next()

Sample code


error_reporting(E_ALL);
/**
 * Script to demonstrate the Iterator pattern
 *
 * 12-Jan-2009
 * @author freedelta, http://freedelta.free.fr
 */

/**
 * Iterator - interface.MyIteratorInt.php
 *
 * Interface that models the Iterator behaviour
 */
interface MyIteratorInt
{
    /**
     * Asks if next element exists
     *
     * @return Boolean      */
    public function hasNext();

    /**      * It returns the object itself
     *      * @return Object      */
    public function next();
}

/**
 * Iterator - class.MyIteratorObj.php  *
 * Class that implements the Iterator interface
 */
class MyIteratorObj implements MyIteratorInt
{
    /**
     * The object to be passed through the constructor parameter
     */
    public $MyObject = null;

    /**
     * A pointer to the current position in the iterator
     */
    public $position = null;
    /**
     * Initializes MyObject and position      * @param  MyIteratorObj MyObject: any tipe of object
    * @throws Exception      */
    public function __construct($MyObject)
    {
        if(!isset($MyObject))         {
            throw new Exception("Collection is empty!");           
        }
        $this->MyObject=$MyObject;
        $this->position=0;
    }

    /**
     * Checks if next item exists
     * @return Boolean
     */
    public function hasNext()
    {   
        // We are on the last item, or array is empty  
        if($this->position >= count($this->MyObject) || $this->MyObject[$this->position]==null)
        {
          return false;
        }         else         {
            return true;
      }
    }

    /**
     * This method is invoked only when we know that hasNext()==true
     * @return Object MyIteratorObj      */
    public function next()
    {
       $item=$this->MyObject[$this->position]; // Get item
        $this->position=$this->position+1;      // Increment position
        return $item;                           // Retrieve item
    }
   
    public function __destruct()
    {   
    }

}

/**  * Iterator - class.Person.php
 *  * Object to test the Iterator pattern  */
 class Person
 {
    protected $name=null;

    public function __construct($name)
    {
        $this->name=$name; 
    }
    public function getName()
    {
        return "My name is: ".$this->name;
    }
 }

// Sample use
 
// Instantiate Persons
$MyObject=array();
$MyObject[0]=new Person("Peter");
$MyObject[1]=new Person("Paul");
$MyObject[2]=new Person("Me");
 
 try
 {
   // Send array of Persons to the Iterator
    $iterator=new MyIteratorObj($MyObject);

    while($iterator->hasNext())
    {
        $currentItem=$iterator->next();
        print " ". $currentItem->getName();
    }

 }
 catch(Exception $e)
 {
    var_dump($e);  }

The output will be:

My name is: Peter
My name is: Paul
My name is: Me