Skip to content
 

Object Iteration in PHP 5

PHP 5 gives us the ability to iterate through objects much as we can with arrays, such as with the foreach() loop construct. I knew this ability existed but had not really looked into it or made use of it. However as a result of a thread at PHPBuilder.com, I thought this might be a good solution.

The key here is that while the default behavior of object iteration is to access each of the object’s public properties, you can override that behavior via the Iterator interface, defining custom methods to iterate what you specifically want from the object.

The following example provides a Thing object which will use the default iterator behavior (public properties). The Thing objects are then collected into the ThingCollection object, which will override the default behavior by implenting the Iterator interface, defining methods to iterate through the private $collection variable, which will be an array of Thing objects.

<?php
/**
 * Sample class for using default iterator behvior on public properties
 */
class Thing {
  public $id;
  public $name;
  public function __construct($id, $name)
  {
    $this->id = (int) $id;
    $this->name = trim($name);
  }
}

/**
 * Sample class that implements Iterator
 * Iterating through this object will use the $collection array
 */
class ThingCollection implements Iterator
{
  /**
  * @var array  A collection of Things
  */
  private $collection = array();

  /**
  * Add a Thing
  * @param object $thing
  */
  public function addThing(Thing $thing)
  {
    $this->collection[] = $thing;
  }

  // Implement the Iterator interface:
  public function rewind()
  {
    reset($this->collection);
  }
  public function current()
  {
    return current($this->collection);
  }
  public function key()
  {
    return key($this->collection);
  }
  public function next()
  {
    return next($this->collection);
  }
  public function valid()
  {
    return $this->current() !== false;
  }
  // End of Iterator methods
}

// create our collection
$test = new ThingCollection();

// add some Things to it
$test->addThing(new Thing(1, 'foo'));
$test->addThing(new Thing(2, 'bar'));

// Let's iterate!
foreach($test as $ix => $thing) // use custom iterator in ThingCollection
{
  echo "<p>Collection index #$ix</p>\n<ul>\n";
  foreach($thing as $key => $value) // use default iterator behavior
  {
    echo "<li>$key: $value</li>\n";
  }
  echo "</ul>\n";
}
?>

This produces the following output:

Collection index #0

  • id: 1
  • name: foo

Collection index #1

  • id: 2
  • name: bar

This allows you to keep the $collection property private (or protected) and under the ThingCollection class’s full control, while making its contents easily accessible via foreach(), instead of having to access it via, perhaps, a ThingCollection::getThingsAsArray() method and then iterating through the array it would return.

Leave a Reply

You must be logged in to post a comment.