Extending an Iterator to use an Iterator to make your code a little cleaner

Monday March 11th, 2013


One of the nice things about iterators is the ability to shove them into other iterators, allowing you to wrap their functionality in other functionality to return a more precise result set. Take for example the idea that we want to read a directory to list only the images inside of it. There are two main ways to do this, via opendir / readdir functions and via FilesystemIterator objects.

Going the FilesystemIterator route, one common way seems to be extend another class called FilterIterator which allows you to customize a filter based on you overwriting a method called accept().

Could not embed GitHub Gist 5136321: Bad credentials

Armed with that class, we could have a bit of code like this…

Could not embed GitHub Gist 5136344: Bad credentials

Which is fine, but if I need to use this ImageFilterIterator multiple times in a code base, not only does that look clumsy but it is super annoying to type. We can clean that up a bit if we extend FilterIterator a little more. Instead of just overriding the accept method, we will also override the __construct.

Could not embed GitHub Gist 5136370: Bad credentials

Now the code that needs this functionality can be reduced down to…

Could not embed GitHub Gist 5136383: Bad credentials

This I find much more tolerable – we have the full power of the FilterIterator running a FilesystemIterator without having to specify that every time we want to read the image directory.

Comment by hakre on Tuesday March 12th at 11:08am
There is also the good old RegexIterator wich can filter based on a regex against current() or key() - http://www.php.net/class.regexiterator - don't miss it ;)
    Comment by bob on Tuesday March 12th at 11:28am

    yep, it's nice. i elected to go with straight filter in this example since regex on the filename isn't a solid test of if the files are images. the accept methods here should be made more in depth for serious use :D
Comment by ashalaenko on Tuesday March 26th at 11:20am
I think in the last example we lost flexibility. What happend when we will get an array of images? Should we recode iterator or create new iterato for this case? In first example we can specify iterator manually and this much better as I think. Sorry for English
    Comment by bob on Tuesday March 26th at 11:32am
    @ashalaenko: then do what you need to do! :)

    the application that i was working on that inspired this will always be reading them from the file system, because that is its one job. this is also only a small example of things you can do, there are lots of iterator classes that can be combined to become useful utilities.
4 Responses to “Extending an Iterator to use an Iterator to make your code a little cleaner”
Write a Comment