Iterators in the Simplest Sense: An Accessible Implementation in PHP 4

In this first article of a series, Alejandro Gervasio explains the core concepts of Iterators in PHP, concentrating most of his efforts on the subject’s practical side.

Introduction

Design Patterns are, in my humble opinion, a very large and complex topic within the universe of software engineering, and certainly when applied particularly to PHP programming, they’re not the exception to the rule. If you’re making your first leaps into the theory and practical implementation of Design Patterns, you may find some of them easier to learn, while others might be harder to grasp, which simply means you’ll need to take more time to master their concepts.

In either case, learning Design Patterns doesn’t have to be a boring and annoying experience which must be avoided at all costs. Indeed, it’s possible to introduce the topic in a friendly way, without appealing to complex definitions or including a lot of buzzwords that may eventually lead you to think erroneously that Design Patterns are out of reach of the average PHP programmer.

However, as you probably know, Design Patterns are a huge topic, which unfortunately can’t be appropriately covered in a few short articles. Bearing in mind this limitation, I’ll start to teach you about Patterns by explaining some of the theory related to the Iterator pattern; at the same time (here’s where things can be interesting for you), I will emphasize its concrete implementation through some specific PHP hands-on examples, which can be quite useful for larger PHP applications.

Here, I’m not going to offer a full reference for what each design pattern is. You can buy a book to learn that, or even do some “googling” and find other helpful resources that probably will treat the subject much more extensively. Instead, I’ll provide you with a concise explanation of what an Iterator is, in conjunction with numerous sample codes, which hopefully will help you understand much more easily how it can applied in PHP object-oriented programming.

After introducing the subject of this series, it’s time to move on and begin learning how the Iterator pattern can work for you. Ready to work with Iterators? Right, let’s get started.

{mospagebreak title=What is an Iterator? defining the core concepts}

Definitely, I’m pretty sure that you’ve heard many times before the term “Iterator”…but, what is it in fact? Essentially, when you’re using an Iterator, what you’re actually doing is creating the necessary programming logic (usually encapsulated inside a class) that will allow you to traverse any data structure by using a common set of methods (this is called an interface too). As I said before, data can be of any type, so whether you’re using arrays, objects, files, directories, or database result sets, an Interator should expose the corresponding methods for iterating over the data structure in question, and manipulating each one of its visible properties.

To clarify the concepts I deployed before, here is a typical signature for an Iterator class in PHP 4, which exposes some of the most common generic methods for traversing a generic data structure:

class MyIterator{
    // constructor
    public function MyIterator($data){
    }
    // method for fetching previous element
    public function previous(){
    }
    // method for fetching current element
    public function current(){
    }
    // method for seeking a particular element
    public function seek(){
    }
    // method for fetching next element
    public function next(){
    }
    // method for checking if current element is valid
    public function valid(){
    }
}

As the above example shows, I defined a generic “MyIterator” class, which exposes a few abstract methods for traversing a generic data structure. If you pay attention to the above class, you’ll realize that it has some intuitive methods for moving back and forward across the structure, such as the “previous()”, “current()” and “next()” methods respectively, and other useful ones, like the “seek()” method, which comes in very handy for navigating to a specified position within the structure. Finally, the “valid()” method should be used for determining whether the current element within the data structure is valid or not.

Of course, eventually I might attach more methods for the above class, but for the moment, the example you just saw should give you a basic idea of how an Iterator works. Asides from the existence of the corresponding class methods, it’s worth nothing that this class isn’t referencing any data structure in particular. All the declared methods are entirely generic and don’t provide a concrete implementation in each case, which is very convenient for achieving a good level of abstraction.

From this point onward, and after having defined the base “MyIterator” class, it’s possible (and certainly recommended) to derive any number of subclasses, which will implement specifically each pertinent method, in order to traverse a specific data structure, that is arrays, objects, files, and so on.

So, that’s a little bit of theory. Now, come with me and read the next section, in order to see how an Iterator can be traduced to real PHP code, so you can start using it in your applications.

{mospagebreak title=Building in an Iterator in PHP 4: setting up a functional example}

One of the best things about PHP is that once the subjacent theory has been understood, translating it into functional code is really simple. This is precisely the case with Iterators, which, as you’ll see soon, are actually simple to code. In order to supply an illustrative example of how to write a working Iterator in PHP 4, what I’ll do next is define an abstract “Iterator” class that has some of the abstract methods I discussed earlier, useful for iterating over a generic data structure. Here’s the source code for this class:

// base abstract ‘Iterator’ class
class Iterator{
    function Iterator(){
        if(get_class($this)==’Iterator’||!is_subclass_of
($this,’Iterator’)){
            trigger_error(‘This class is abstract. It cannot be
instantiated!’,E_USER_ERROR);
        }
    }
    // abstract ‘current()’ method
    function current(){}
    // abstract ‘prev()’ method
    function prev(){}
    // abstract ‘next()’ method
    function next(){}
    // abstract ‘end’ method
    function end(){}
    // abstract ‘reset()’ method
    function reset(){}
    // abstract ‘seek()’ method
    function seek(){}
    // abstract ‘count()’ method
    function count(){}      
}

That’s it. I told you it was really easy! As you can see, I defined the above class in such a way that it exposes a few methods for traversing a data structure of any type. Also, I defined this class as abstract, by including a checking block inside the constructor. This prevents the class from being instantiated, either when directly called within client code, or when invoked from inside a non-subclass.

Essentially, this sample “Iterator” class has seven different methods for iterating and processing data. It’s clear to see that each of them are extremely intuitive and understandable. Although none of these methods exposes a concrete implementation within the corresponding class, their names are suggestive enough to indicate what they’ll do when they’re concretely defined.

In accordance with the concepts I explained above, the “reset()”, “prev()”, “current()”, “next()” and “end()” methods should be defined within the pertinent subclasses, so they must provide an easy way to move back and forth across a particular data structure. In a similar fashion, the “seek()” and count()” method should be defined in order to allow the seeking of a specific element, and the counting of the number of elements that comprise the structure itself.

Okay, at this point you know how a generic Iterator looks. Now, it’s time to do something useful with this powerful structure, so it can be used within a PHP application. Want to learn how to build an array Iterator, using the base class you just learned? Go ahead and read the next section.

{mospagebreak title=Deriving subclasses from the base Iterator: building an array Iterator class}

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!

Google+ Comments

Google+ Comments