Iterators in the Simplest Sense: An Accessible Implementation in PHP 4 - Deriving subclasses from the base Iterator: building an array Iterator class (
Page 4 of 4 )
After defining the base “Iterator” class that I explained in the previous section, the process of creating an array iterator class is really straightforward. The whole task is reduced to deriving a subclass from this parent class, as shown below:
// 'ArrayIterator' subclass
class ArrayIterator extends Iterator{
var $data=array();
function ArrayIterator($data=array()){
if(!is_array($data)){
trigger_error('Data must be an array',E_USER_ERROR);
}
$this->data=$data;
}
// concrete implementation for 'current()' method
function current(){
if(!$data=current($this->data)){
trigger_error('Error retrieving current
element',E_USER_ERROR);
}
return $data;
}
// concrete implementation for 'prev()' method
function prev(){
if(!$data=prev($this->data)){
trigger_error('Error retrieving previous
element',E_USER_ERROR);
}
return $data;
}
// concrete implementation for 'next()' method
function next(){
if(!$data=next($this->data)){
trigger_error('Error retrieving next
element',E_USER_ERROR);
}
return $data;
}
// concrete implementation for 'end()' method
function end(){
if(!$data=end($this->data)){
trigger_error('Error retrieving last
element',E_USER_ERROR);
}
return $data;
}
// concrete implementation for 'reset()' method
function reset(){
if(!$data=reset($this->data)){
trigger_error('Error retrieving first
element',E_USER_ERROR);
}
return $data;
}
// concrete implementation for 'seek()' method
function seek($pos){
if(!is_int($pos)&&$pos<0){
trigger_error('Invalid offset',E_USER_ERROR);
}
if(!$data=$this->data[$pos]){
trigger_error('Error seeking element',E_USER_ERROR);
}
return $data;
}
// concrete implementation for 'count()' method
function count(){
if(!$data=count($this->data)){
trigger_error('Error counting
elements',E_USER_ERROR);
}
return $data;
}
}
Now, you’ll agree I did something useful with the base Iterator class you saw earlier. As you can see, I derived a subclass and created a functional array iterator class, by coding an explicit definition for each of the generic methods of the base class. Not rocket science, right?
In addition, here’s a simple snippet that shows a concrete application for this sample array iterator. Take a look:
$testarray=array('Element1','Element2','Element3','Element4');
$aIterator=&new ArrayIterator($testarray);
// display first array element
echo $aIterator->reset();
// display current array element
echo $aIterator->current();
// display next array element
echo $aIterator->next();
// display final array element
echo $aIterator->end();
// display previous array element
echo $aIterator->prev();
// count array elements
echo $aIterator->count();
// seek array element
echo $aIterator->seek(2);
Notice how each one of the corresponding methods has been written, in order to allow traversing easily any array passed as an argument to the class constructor. In addition, it’s also possible to count the number of elements within the array, or search a specific element in the structure, by using the “count()” and “seek()” methods respectively.
At this stage, I hope you learned the basic theory of Iterators in PHP, along with an understandable-–yet useful--concrete implementation: the development of an array iterator. However, admittedly an array iterator isn’t a very useful thing on its own, and should be integrated as a building block for more complex applications. But in fact, I’m getting ahead of myself, so please be patient and read the concluding thoughts.
Bottom line
In this first article of the series, I’ve explained the core concepts of Iterators in PHP, concentrating most of my efforts on the subject’s practical side. As you’ve seen in this tutorial, an array iterator is a powerful structure that can be used to step up to building the logic of larger PHP applications.
Keeping this idea in mind, in the next article I’ll show you how to use this array iterator for creating a couple of useful applications, handy for traversing flat files and MySQL result sets. You don’t have any excuses to miss it!