Create a gist now

Instantly share code, notes, and snippets.

What would you like to do?
Advanced PHP Interface Example: Traversable and Countable extended
<?php
/**
* Advanced PHP Interface Example: Traversable and Countable extended
*
* As Traversable is an internal interface but PHP interfaces allow to extend
* from multiple interfaces, it is possible to create your own internal
* type (here based on Traversable) and base another non-internal sub-type
* on it (here based on IteratorAggregate).
*
* @link http://wpkrauts.com/2013/how-to-build-flexible-php-interfaces/
* @link https://eval.in/39494
*/
interface CountableTraversable
extends Traversable, Countable
{
}
interface CountableTraversableAggregate
extends CountableTraversable, IteratorAggregate
{
}
class Widgets implements CountableTraversableAggregate
{
private $widgets = array('Blue', 'Red');
function getIterator()
{
return new ArrayIterator($this->widgets);
}
function count()
{
return count($this->widgets);
}
}
$widgets = new Widgets();
printf("You have %d widgets:\n", count($widgets));
foreach($widgets as $key => $widget) {
printf("[%s]: %s\n", $key, $widget);
}

Another option to loop through the array would be to use the Iterator methods directly:

$widgets = ( new Widgets() )->getIterator();
$widgets->rewind();

printf( "You have %d widgets:\n", count( $widgets ) );

while( $widgets->valid() ) {
    printf ("[%d]: %s\n", $widgets->key(), $widgets->current() );
    $widgets->next();
}

which , in theory, should scale better memory wise with increasing size of the looped array. Also it's good habit to actually rewind() an Iterator before a loop as it could be stuck somewhere in the middle from a previous, interrupted loop.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment