Using an Iterator Interface to Create “Round-Robin” Array

I had a requirement that seemed to need a way to cycle through a set of values in an array in such a way that when I got to the end of the array, it would start over at the beginning, essentially load-balancing the use of those array elements. Perhaps you might want to do the same thing for a set of ads, making sure a given user sees each available advertisement before starting again with the first (perhaps an array stored in $_SESSION?).

After exploring a few alternatives, one I found that I kind of like (for its elegance if not its lack of brevity) was to use PHP’s built-in Iterator interface. The concept here was to load any array into an instance of a class that implements the Iterator, and then simply using the Iterator::next() method to get the current value, then advance the array pointer, pointing it back to the beginning if it has reached the end of the array. Without further ado, the class:


<?php

class RoundRobin implements Iterator
{
    private 
$var = array();

    public function 
__construct($array)
    {
        if (
is_array($array)) {
            
$this->var $array;
        }
    }

    public function 
rewind()
    {
        
reset($this->var);
    }

    public function 
current()
    {
        return 
current($this->var);
    }

    public function 
key()
    {
        return 
key($this->var);
    }

    
/**
     * Get the current array element, then advance the pointer
     * @return mixed
     */
    
public function next()
    {
        
$var current($this->var);
        
next($this->var);
        if(!
$this->valid()) {
            
$this->rewind();
        }
        return 
$var;
    }

    public function 
valid()
    {
        
$key key($this->var);
        return (
$key !== NULL && $key !== FALSE);
    }
}

A sample usage:


<?php

$data 
= new RoundRobin(range(1,10));
$dbStuff getLotsOfStuffFromTheDB();
foreach(
$dbStuff as $stuff) {
    
$result getSomeMoreStuff($dbStuff['foo'], $data->next());
}

Danger, Will Robinson. Don’t do this, or you’ll have an endless loop:


<?php

$data 
= new RoundRobin(range(1,10));
foreach(
$data as $foo) {
    echo 
$foo "<br />\n";
}

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.

Continue reading “Object Iteration in PHP 5”