Introduction to Standard PHP Library-SPL Part-1
Today I’ll look at some iterators: a set of classes in the SPL that implements various iterating patterns: ArrayIterator, AppendIterator,FilterIterator. Hopefully you’ll get a idea of what these are capable of and that you can get some new ideas for your day-to-day tasks.
What is SPL.
SPL provides a standard set of interfaces for PHP5. The aim of SPL is to implement some efficient data access interfaces and classes for PHP. Functionally it is designed to traverse aggregate structures (anything you want to loop over). These may include arrays, database result sets, xml trees, directory listings or any list at all. Currently SPL deals with Iterator. To see all the classes available to SPL, this simple snippet will show you.
</p> <?php // a simple foreach() to traverse the SPL class names foreach(spl_classes() as $key=>$value) { echo $key.' -> '.$value.'<br />'; } ?>
This will provide you with a list something like this:
- AppendIterator -> AppendIterator
- ArrayIterator -> ArrayIterator
- ArrayObject -> ArrayObject
- BadFunctionCallException -> BadFunctionCallException
- BadMethodCallException -> BadMethodCallException
- CachingIterator -> CachingIterator
- Countable -> Countable
- DirectoryIterator -> DirectoryIterator
- DomainException -> DomainException
- EmptyIterator -> EmptyIterator
- FilterIterator -> FilterIterator
- InfiniteIterator -> InfiniteIterator
- InvalidArgumentException -> InvalidArgumentException
- IteratorIterator -> IteratorIterator
- LengthException -> LengthException
- LimitIterator -> LimitIterator
- LogicException -> LogicException
- NoRewindIterator -> NoRewindIterator
- OuterIterator -> OuterIterator
- OutOfBoundsException -> OutOfBoundsException
- OutOfRangeException -> OutOfRangeException
- OverflowException -> OverflowException
- ParentIterator -> ParentIterator
- RangeException -> RangeException
- RecursiveArrayIterator -> RecursiveArrayIterator
- RecursiveCachingIterator -> RecursiveCachingIterator
- RecursiveDirectoryIterator -> RecursiveDirectoryIterator
- RecursiveFilterIterator -> RecursiveFilterIterator
- RecursiveIterator -> RecursiveIterator
- RecursiveIteratorIterator -> RecursiveIteratorIterator
- RecursiveRegexIterator -> RecursiveRegexIterator
- RegexIterator -> RegexIterator
- RuntimeException -> RuntimeException
- SeekableIterator -> SeekableIterator
- SimpleXMLIterator -> SimpleXMLIterator
- SplFileInfo -> SplFileInfo
- SplFileObject -> SplFileObject
- SplObjectStorage -> SplObjectStorage
- SplObserver -> SplObserver
- SplSubject -> SplSubject
- SplTempFileObject -> SplTempFileObject
- UnderflowException -> UnderflowException
- UnexpectedValueException -> UnexpectedValueException
What are iterators?
An Iterator is an object that traverses a structure eg: an array or a directory listing or possibly a set of database result sets or other resource. This is not an accurate description, but more will become clear later by way of example. There are different types of Iterators for dealing with different types of data such as array Iterators, Directory Iterators and more. Here we will begin to get familiar with them beginning with the DirectoryIterator. What is important to note is they can all be accessed with a standard interface. This means that regardless of the data type, access to the information is standardized. This is a real step forward for PHP.
ArrayIterator
The ArrayIterator does exactly what it tells you: it’s used to iterate over an array of values, with it you can easily iterate over values like you would any other collection with a normal iterator. It has the ability to seek and rewind on the array in question and get the current key and value.
ArrayIterator::current
ArrayIterator::current — Return current array entry
Example #1 ArrayIterator::current() example
File: array_iterator_current.php
<?php $array = array('1' => 'one', '2' => 'two', '3' => 'three'); $arrayobject = new ArrayObject($array); for($iterator = $arrayobject->getIterator(); $iterator->valid(); $iterator->next()) { echo $iterator->key() . ' => ' . $iterator->current() . "\n"; } ?>
The above example will output:
1 => one
2 => two
3 => three
ArrayIterator::next
ArrayIterator::next — Move to next entry
Example #1 ArrayIterator::next() example
File: array_iterator_next.php
<?php $arrayobject = new ArrayObject(); $arrayobject[] = 'zero'; $arrayobject[] = 'one'; $iterator = $arrayobject->getIterator(); while($iterator->valid()) { echo $iterator->key() . ' => ' . $iterator->current() . "\n"; $iterator->next(); } ?>
The above example will output:
0 => zero
1 => one
ArrayIterator::rewind — Rewind array back to the start
Example #1 ArrayIterator::rewind() example
File: array_iterator_rewind.php
<?php $arrayobject = new ArrayObject(); $arrayobject[] = 'zero'; $arrayobject[] = 'one'; $arrayobject[] = 'two'; $iterator = $arrayobject->getIterator(); $iterator->next(); echo $iterator->key(); //1 $iterator->rewind(); //rewinding to the begining echo $iterator->key(); //0 ?>
ArrayIterator::valid
ArrayIterator::valid — Check whether array contains more entries
Example #1 ArrayIterator::valid() example
File: array_iterator_valid.php
<?php $array = array('1' => 'one'); $arrayobject = new ArrayObject($array); $iterator = $arrayobject->getIterator(); var_dump($iterator->valid()); //bool(true) $iterator->next(); // advance to the next item //bool(false) because there is only one array element var_dump($iterator->valid()); ?>
AppendIterator
In the example above we looked at how we can iterate over a single ArrayObject and how the IteratorAggregate interface works, but: if you have multiple elements you might want to iterate over all of these together, this is where the AppendIterator comes to help you.
The following example creates two ArrayObjects and a AppendIterator, there is only a single method here that you need to think about, the append() function that takes a Iterator as argument. The point of the iterator is to collect several collections and iterate over them in one go:
AppendIterator::append
AppendIterator::append — Appends an iterator
Example #1 AppendIterator::append() example
File: append_iterator_append.php
<?php $array_a = new ArrayIterator(array('a', 'b', 'c')); $array_b = new ArrayIterator(array('d', 'e', 'f')); $iterator = new AppendIterator; $iterator->append($array_a); $iterator->append($array_b); foreach ($iterator as $current) { echo $current; } ?>
The above example will output:
Abcdef AppendIterator::__construct
AppendIterator::__construct — Constructs an AppendIterator
Example #1 Iterating AppendIterator with foreach
File: Iterating_AppendIterator_with_foreach.php
<?php $pizzas = new ArrayIterator(array('Margarita', 'Siciliana', 'Hawaii')); $toppings = new ArrayIterator(array('Cheese', 'Anchovies', 'Olives', 'Pineapple', 'Ham')); $appendIterator = new AppendIterator; $appendIterator->append($pizzas); $appendIterator->append($toppings); foreach ($appendIterator as $key => $item) { echo $key . ' => ' . $item . PHP_EOL; } ?>
The above example will output:
0 => Margarita 1 => Siciliana 2 => Hawaii 0 => Cheese 1 => Anchovies 2 => Olives 3 => Pineapple 4 => Ham Example #2 Iterating AppendIterator with the AppendIterator API
File: Iterating_AppendIterator_with_the_AppendIterator_API.php
<?php $pizzas = new ArrayIterator(array('Margarita', 'Siciliana', 'Hawaii')); $toppings = new ArrayIterator(array('Cheese', 'Anchovies', 'Olives', 'Pineapple', 'Ham')); $appendIterator = new AppendIterator; $appendIterator->append($pizzas); $appendIterator->append($toppings); while ($appendIterator->valid()) { printf( '%s => %s => %s%s', $appendIterator->getIteratorIndex(), $appendIterator->key(), $appendIterator->current(), PHP_EOL ); $appendIterator->next(); } ?>
The above example will output:
0 => 0 => Margarita 0 => 1 => Siciliana 0 => 2 => Hawaii 1 => 0 => Cheese 1 => 1 => Anchovies 1 => 2 => Olives 1 => 3 => Pineapple 1 => 4 => Ham AppendIterator::getInnerIterator
This method returns the current inner iterator.
Example #1 AppendIterator::getInnerIterator() example
File: append_iterator_get_inner_iterator.php
<?php $array_a = new ArrayIterator(array('a' => 'aardwolf', 'b' => 'bear', 'c' => 'capybara')); $array_b = new RegexIterator($array_a, '/^[ac]/'); $iterator = new AppendIterator; $iterator->append($array_a); $iterator->append($array_b); foreach ($iterator as $current) { $inner = $iterator->getInnerIterator(); if ($inner instanceOf RegexIterator) { echo 'Filtered: '; } else { echo 'Original: '; } echo $current . PHP_EOL; } ?>
The above example will output:
Original: aardwolf Original: bear Original: capybara Filtered: aardwolf Filtered: capybara AppendIterator::getIteratorIndex
AppendIterator::getIteratorIndex — Gets an index of iterators
Example #1 AppendIterator.getIteratorIndex() basic example
File: AppendIterator.getIteratorIndex.php
<?php $array_a = new ArrayIterator(array('a' => 'aardwolf', 'b' => 'bear', 'c' => 'capybara')); $array_b = new ArrayIterator(array('apple', 'orange', 'lemon')); $iterator = new AppendIterator; $iterator->append($array_a); $iterator->append($array_b); foreach ($iterator as $key => $current) { echo $iterator->getIteratorIndex() . ' ' . $key . ' ' . $current . PHP_EOL; } ?>
The above example will output:
0 a aardwolf 0 b bear 0 c capybara 1 0 apple 1 1 orange 1 2 lemon AppendIterator::key
AppendIterator::key — Gets the current key
Example #1 AppendIterator::key() basic example
File: AppendIterator_key.php
<?php $array_a = new ArrayIterator(array('a' => 'aardwolf', 'b' => 'bear', 'c' => 'capybara')); $array_b = new ArrayIterator(array('apple', 'orange', 'lemon')); $iterator = new AppendIterator; $iterator->append($array_a); $iterator->append($array_b); // Manual iteration $iterator->rewind(); while ($iterator->valid()) { echo $iterator->key() . ' ' . $iterator->current() . PHP_EOL; $iterator->next(); } echo PHP_EOL; // With foreach foreach ($iterator as $key => $current) { echo $key . ' ' . $current . PHP_EOL; } ?>
The above example will output:
The above example will output:
a aardwolf b bear c capybara 0 apple 1 orange 2 lemon
a aardwolf
b bear
c capybara
0 apple
1 orange
2 lemon
FilterIterator
By now you should be getting in the swing of iterators. The FilterIterator is and abstract class and is the same as other iterators and we can also overload the FilterIterator class by extending it. This allows us to filter out any unwanted data from our aggregate structure, in this case an array of elements from the periodic table. First, lets look at the available methods to the FilterIterator. The FilterIterator is perhaps the easiest of all iterators to use. Simply by calling the accept method and specifying your filter requirements there.
File: get_filter_iterator_methods.php <?php /*** list all class methods ***/ foreach( get_class_methods(FilterIterator) as $methodName) { echo $methodName.'<br />'; } ?>
The snippet above will produce a list of methods in the FilterIterator like this:
__construct
rewind
valid
key
current
next
getInnerIterator
accept
This list should look rather familiar by now as we see it is basically a simple iterator with a few only a fewextra methods. The method we are most concerned with here is the accept() method. By implementing the accept method we can filter out all but the information we want, or do not want. We can even make changes to data within the accept method. Here we will extend the FilterIterator class and use the accept method to cull a few kiwis from an array of Australian natives.
File: File: filter_iterator_accept1.php
<?php /*** a simple array ***/ $animals = array('koala', 'kangaroo', 'wombat', 'wallaby', 'emu', 'NZ'=>'kiwi', 'kookaburra', 'platypus'); class CullingIterator extends FilterIterator{ /*** The filteriterator takesa iterator as param: ***/ public function __construct( Iterator $it ){ parent::__construct( $it ); } /*** check if key is numeric ***/ function accept(){ return is_numeric($this->key()); } }/*** end of class ***/ $cull = new CullingIterator(new ArrayIterator($animals)); foreach($cull as $key=>$value) { echo $key.' == '.$value.'<br />'; } ?>
The above code will produce a list as follows:
0 == koala
1 == kangaroo
2 == wombat
3 == wallaby
4 == emu
5 == kookaburra
6 == platypus
As we iterate over the array the accept() method is called to see wether the current key is valid, in this case, if it is numeric as checked with the PHP is_numeric() function. should be accepted. Of course we could do other tricks within the accept method as seen here as we filter out the prime numbers from an array of numbers.
File: filter_iterator_accept3.php
<pre><?php class PrimeFilter extends FilterIterator{ /*** The filteriterator takesa iterator as param: ***/ public function __construct(Iterator $it){ parent::__construct($it); } /*** check if current value is prime ***/ function accept(){ if($this->current() % 2 != 1) { return false; } $d = 3; $x = sqrt($this->current()); while ($this->current() % $d != 0 && $d < $x) { $d += 2; } return (($this->current() % $d == 0 && $this->current() != $d) * 1) == 0 ? true : false; } }/*** end of class ***/ /*** an array of numbers ***/ $numbers = range(212345,212456); /*** create a new FilterIterator object ***/ $primes = new primeFilter(new ArrayIterator($numbers)); foreach($primes as $value) { echo $value.' is prime.<br />'; } ?>
From the above code we get a list of the prime numbers between 212345 and 212456 as shown here:
212353 is prime.
212369 is prime.
212383 is prime.
212411 is prime.
212419 is prime.
212423 is prime.
212437 is prime.
212447 is prime.
212453 is prime.
This sort of filtering makes the FilterIterator quite a useful tool for aggregate stuctures. Remember, the data could be XML or database results and with the FilterIterator you can specify whatever rules you like in the accept() method. The job of the accept() method is to decide whether an element of the inner iterator should be accessible through the Filteriterator. The inner iterator in the case above is the ArrayIterator.
Oh, and if you think you have a better prime number checking algorithm, please submit it and we will include it.
FilterIterator::accept Another Example FilterIterator::accept — Check whether the current element of the iterator is acceptable
Example #1 FilterIterator::accept() example
File: filter_iterator_accept2.php
<?php // This iterator filters all values with less than 10 characters class LengthFilterIterator extends FilterIterator { public function accept() { // Only accept strings with a length of 10 and greater return strlen(parent::current()) > 10; } } $arrayIterator = new ArrayIterator(array('test1', 'more than 10 characters')); $lengthFilter = new LengthFilterIterator($arrayIterator); foreach ($lengthFilter as $value) { echo $value . "\n"; } ?>
The above example will output:
more than 10 characters
There are many ways to iterate over a collection of items, but you might not want to display everything at any given time; say hello to the FilterIterator, a abstract class that have one function you will need to implement: accept.
<?php /** * Our filter, it implements the accept() function, * this is where we decide what will be accepted by * the foreach further down */ class Filter extends FilterIterator { /** * The filteriterator needs a iterator as param: */public function __construct( Iterator $it ) { parent::__construct( $it ); } /** * When we iterate over the array the following * function will be called to see wether we should * accept the current key: */public function accept() { if( preg_match( "/^php/", $this->getInnerIterator()->key() ) ) { return true; } return false; } } $arr = array( "php" => "php.net", "php_pecl" => "pecl.php.net", "perl" => "perl.org", "python" => "python.org" ); $obj = new ArrayObject( $arr ); $it = new Filter( $obj->getIterator() ); foreach( $it as $key => $value ) { echo "key=$key, value=$value\n"; } ?>
Running this will give us ( as we would suspect ) the following:
key=php, value=php.net key=php_pecl, value=pecl.php.net
And we have successfully filtered out anything where the key doesn’t start with php.
A FilterIterator can be very useful when you are iterating over items and want to automaticly check the current item before outputting it ( a “adult filter” can be one example of what you want to implement ).

Hi, My name is Masud Alam, love to work with Open Source Technologies, living in Dhaka, Bangladesh. I’m a Certified Engineer on ZEND PHP 5.3, I served my first Fifteen years a number of leadership positions at AmarBebsha Ltd as a CTO, Winux Soft Ltd, SSL Wireless Ltd, Canadian International Development Agency (CIDA), World Vision, Care Bangladesh, Helen Keller, US AID and MAX Group where I worked on ERP software and web development., but now I’m a founder and CEO of TechBeeo Software Company Ltd. I’m also a Course Instructor of ZCPE PHP 7 Certification and professional web development course at w3programmers Training Institute – a leading Training Institute in the country.
This is very good and helpful tutorial.I have also some helpful tutorial about PDO on my blog.
Hi, Thank you for this examples. Very helpful.
I have a question:
if i comment out the line below in the filter iterator example, the code still works. Should I include that? if yes, why?
code i commented out:
/*** The filteriterator takesa iterator as param: ***/
public function __construct( Iterator $it ){
parent::__construct( $it );
}