The Iterator Pattern: OOP Techniques in PHP
Posted on 04. Mar, 2009 by Will Fitch in PHP
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
Countable Interface
-
<?php
-
interface Countable
-
{
-
}
-
?>
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
-
*/
-
-
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
-
*/
-
-
/**
-
* Position of the iterator
-
*/
-
private $position=0;
-
-
/**
-
* Retrieve the current record
-
*/
-
{
-
return $this->users[$this->position];
-
}
-
-
/**
-
* Return the current key index
-
*/
-
{
-
return $this->position;
-
}
-
-
/**
-
* Increment the iterator index
-
*/
-
{
-
++$this->position;
-
}
-
-
/**
-
* Reset the position
-
*/
-
{
-
$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 the total number of 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
-
}
-
// Rewind the iterator
-
$iterator->rewind();
-
-
while ($iterator->valid())
-
{
-
$value = $iterator->current();
-
$iterator->next();
-
}
-
-
// Rewind the iterator
-
$iterator->rewind();
-
-
for ($iterator->key(); $iterator->valid(); $iterator->next())
-
{
-
$value = $iterator->current();
-
}
-
-
?>
Conclusion
This is a much cleaner, easier approach to iterating over objects. I hope you find this usable in your domain models!


![[del.icio.us]](http://www.willfitch.com/wp-content/plugins/bookmarkify/delicious.png)
![[Digg]](http://www.willfitch.com/wp-content/plugins/bookmarkify/digg.png)
![[Google]](http://www.willfitch.com/wp-content/plugins/bookmarkify/google.png)
![[LinkedIn]](http://www.willfitch.com/wp-content/plugins/bookmarkify/linkedin.png)
![[StumbleUpon]](http://www.willfitch.com/wp-content/plugins/bookmarkify/stumbleupon.png)
![[Windows Live]](http://www.willfitch.com/wp-content/plugins/bookmarkify/windowslive.png)
![[Yahoo!]](http://www.willfitch.com/wp-content/plugins/bookmarkify/yahoo.png)
![[Email]](http://www.willfitch.com/wp-content/plugins/bookmarkify/email.png)


Adaptor
26. Jul, 2009
Thanks for the clear explanation!
Will Fitch
10. Feb, 2010
No problem! Glad it helped.