Porto

SPL AppendIterator

SPL AppendIterator

By Kevin Waterson

Contents

  1. Abstract
  2. Reflection
  3. Appending Arrays
  4. Filtering Multiple Arrays

Abstract

The SPL AppendIterator provides a method of iterating over multiple arrays at the same time. This can be very useful when aggregating data from different sources, such as XML or RSS feeds or even multiple database sources. The flexibility and efficiency of the whole SPL suite of tools is a the disposal of the AppendIterator making manipulating data in multiple objects fast and simple with a minimum of code.

Reflection

Using the Reflection API the internals of the AppendIterator are easy to see.


<?php
    Reflection
::export(new ReflectionClass('AppendIterator'));
?>
Class [   class AppendIterator extends IteratorIterator implements OuterIterator, Traversable, Iterator ] {

  - Constants [0] {
  }

  - Static properties [0] {
  }

  - Static methods [0] {
  }

  - Properties [0] {
  }

  - Methods [10] {
    Method [  public method __construct ] {
    }

    Method [  public method append ] {
      - Parameters [1] {
        Parameter #0 [  Iterator $iterator ]
      }
    }

    Method [  public method rewind ] {
    }

    Method [  public method valid ] {
    }

    Method [  public method key ] {
    }

    Method [  public method current ] {
    }

    Method [  public method next ] {
    }

    Method [  public method getInnerIterator ] {
    }

    Method [  public method getIteratorIndex ] {
    }

    Method [  public method getArrayIterator ] {
    }

  }

}

Appending Arrays

As seen from the reflection output above, the AppendIterator has much the same API as other iterator classes. The primary method that does the work however, is the append() method. which the AppendIterator uses append an iterator object to an aggregated iterator. To append to the AppendIterator, a new AppendIterator object is created and iterator objects added to it as shown here.


<?php
    
/*** first array of australian animals ***/
    
$array1 = new ArrayIterator( array('dingo''wombat''steve irwin') );
    
    
/*** second array of australian animals ***/
    
$array2 = new ArrayIterator( array('platypus''wallaby''kiwi') );

    
/*** third array of australian animals ***/
    
$array3 = new ArrayIterator( array('koala''kangaroo''kookaburra') );

    
/*** a new AppendIterator object ***/
    
$it = new AppendIterator();

    
/*** append the arrays ***/
    
$it->append($array1);
    
$it->append($array2);
    
$it->append($array3);

     
/*** loop over and print each animal ***/
    
foreach($it as $key => $aussie)
    {
        echo 
$key.' = '.$aussie.'<br />';
    }
?>

The order in which the each array is traversed is apparent when the keys are displayed also. Each array is iterated over in order they were appended to the AppendIterator.

0 = dingo
1 = wombat
2 = steve irwin
0 = platypus
1 = wallaby
2 = kiwi
0 = koala
1 = kangaroo
2 = kookaburra

The greatest benifit of using the AppendIterator is that any of the SPL Iterator suite can now be used in conjunction with the iterator object.

Filtering Mulitple Arrays

In the second array, a kiwi is present. The kiwi is a New Zealand bird and not part of the Australian fauna. The offending critter can be filtered out with the SPL FilterIterator.


<?php
    
/*** first array of australian animals ***/
    
$array1 = new ArrayIterator( array('dingo''wombat''steve irwin') );

    
/*** second array of australian animals ***/
    
$array2 = new ArrayIterator( array('platypus''wallaby''kiwi') );

    
/*** third array of australian animals ***/
    
$array3 = new ArrayIterator( array('koala''kangaroo''kookaburra') );

    
/*** a new AppendIterator object ***/
    
$it = new AppendIterator();

    
/*** append the arrays ***/
    
$it->append(new kiwiFilter$array1) );
    
$it->append(new kiwiFilter$array2) );
    
$it->append(new kiwiFilter$array3) );

    
/*** loop over and print each animal ***/
    
foreach($it as $key => $aussie)
    {
        echo 
$key.' = '.$aussie.'<br />';
    }

    
/**
     * @Class to filter out kiwis
     *
     */
    
class kiwiFilter extends FilterIterator
    
{
        
/**
         * Constructor - Calls parent FilterIterator class
         *
         * @param Iterator $it - An iterator object
         *
         */
        
public function __constructIterator $it )
        {
            
parent::__construct$it );
        }

        
/**
         *
         * @accept only values that are not kiwis
         *
         * @return string
         *
         */
        
public function accept()
        {
            return 
$this->current() != 'kiwi';
        }
    } 
/*** end of kiwiFilter class ***/
        
?>

And from the above code, the results look like this:

0 = dingo
1 = wombat
2 = steve irwin
0 = platypus
1 = wallaby
0 = koala
1 = kangaroo
2 = kookaburra

This time when the foreach loop is run, the offending kiwi has been filtered out of the array. Any of the classes, or interfaces are available when traversing mulitple arrays, making for quick and easy aggregation an manipulation of data in an efficient manner.