The iterator pattern is one of the most useful, yet unused patterns defined. It provides a way for class users to count and iterate over a set of objects related to the class. This is very useful in MVC (Model-View-Controller) models as they handle data and the logic that pertains to it.
PHP provides two interfaces that already define what you should include in an iterator pattern: Iterator and Countable. Below are their definitions:
Iterator Interface
<?php interface Iterator implements Traversable { public mixed current(); public scalar key(); public void next(); public void rewind(); public bool valid(); } ?>
Countable Interface
<?php interface Countable { public int count(); } ?>
You can already iterate over class properties using the foreach() loop, so the Iterator and Countable interfaces are domain specific — meaning the iteration logic is specific to the functionality of the class.
As an example, let’s assume we have a domain model that manages users (CRUD). We have an additional class that acts as a structure (you don’t have to do this, but it’s easier to read in a blog) for each individual user. You also have a method that retrieves an arbitrary number of users, assigns each to a User class (acting as a struct), and gives back an array. While this is certainly doable, the iterator pattern defines an easier way to process the data.
Example Before Iterator Pattern
<?php class User { public $email; public $address; public $city; public $state; public $zip; } class User_Management { /** * List of users */ private $users=array(); public function getUserByID($id) { // go get a user and assign it an instance of User } public function getAllUsers() { // go get all users, assign each to User class, and add to the self::users array } } ?>
The above example is pretty typical for domain models without the use of iterator. Adding the iterator, we provide an interface to bi-directionally traverse, get key information and count records.
With the Iterator Pattern Implemented
<?php class User { public $email; public $address; public $city; public $state; public $zip; } class User_Management implements Iterator, Countable { /** * List of users */ private $users=array(); /** * Position of the iterator */ private $position=0; /** * Retrieve the current record */ public function current() { return $this->users[$this->position]; } /** * Return the current key index */ public function key() { return $this->position; } /** * Increment the iterator index */ public function next() { ++$this->position; } /** * Reset the position */ public function rewind() { $this->position = 0; } public function getUserByID($id) { // go get a user and assign it an instance of User } /** * Validate whether a record at current * position exists */ public function valid() { return (isset($this->users[$this->position])); } /** * Return the total number of users */ public function count() { return count($this->users); } public function getAllUsers() { // go get all users, assign each to User class, and add to the self::users array } } ?>
The domain model now implements Countable and Iterator. The below example shows a couple of uses for this:
<?php $iterator = new User_Management(); foreach ($iterator as $index => $value) { // The $index will contain the current key // while the $value will contain the user // at the current position echo $value->address; } // Rewind the iterator $iterator->rewind(); while ($iterator->valid()) { $value = $iterator->current(); echo $value->address; $iterator->next(); } // Rewind the iterator $iterator->rewind(); for ($iterator->key(); $iterator->valid(); $iterator->next()) { $value = $iterator->current(); echo $value->address; } ?>
Conclusion
This is a much cleaner, easier approach to iterating over objects. I hope you find this usable in your domain models!












Thanks for the clear explanation!
No problem! Glad it helped.
[...] to the class. This is very useful in MVC (Model-View-Controller) models as they handle data… [full post] Will Fitch Will Fitch's Blog phptutorialsiteratoroop 0 0 0 [...]