SPL: The hidden gem

By a show of hands, how many people here have ever heard of SPL? How many have used it? Chances are most of you did not raise your hands, and some might even have a confused look on their faces. Not many know what SPL is, so let’s explore.

SPL, or Standard PHP Library, is a set of classes and interfaces that have been built in to PHP since version 5.0, and as of PHP 5.3 it cannot even be disabled, so it is here for good. Its actually hard to disable it when compiling, so 9.9 out of 10 times you can be sure that you have it. But why have you not used it? The answer begins with “poor documentation” and ends in “didn’t even know it existed”. SPL has not had the promotion that it deserves – but this article hopes to remedy that! So what is in SPL?

SPL makes available a few hooks for overloading the PHP Engine, such as ArrayAccess, Countable and SeekableIterator interfaces, to make your objects work like arrays. You can also manipulate other stuff using RecursiveIterator, ArrayObejcts and various other iterators. It even has classes for specific points such as Exceptions, SplObserver, Spltorage and helper functions to overload other aspects, like spl_autoload_register, spl_classes and iterator_apply. Overall its a swiss army knife of code that can be implemented in PHP but that because of its hooks will probably perform much faster in SPL. So, what can I actually do with it then?

Overloading autoloader

You are a by the book programmer, and after __autoload came around you rewrote all your sites and removed the endless stream os includes and requires in your code to make way for lazy loading, right? So once in a while you found yourself in a jam, your product’s classes use a specific naming/directory structure and the Zend Framework classes you use have a “_” to path approach, how do you solve this? Giant __autoload that includes all logic, trial and error style? Alter you directory structure to Zend’s? No! Overload it!

The process is simple, just create your own autoload function and overload it, that way the autoload procedure will run the class through Zend’s loader, if it does not find a class, it will then run yours, and keep on going down the line until one of them finds it.

    1 <?php
    2
    3 class MyLoader{
    4     public static function doAutoload($class){
    5         //autoload process
    6         //use file_exists please
    7     }
    8 }
    9
   10 spl_autoload_register( array('MyLoader', 'doAutoload') );
   11
   12 ?>

Iterators

Iterator is a design pattern, a generic solution to iterate over data in a consistent manner, a way to access elements of an object in a sequential way without exposing underlying representations. SPL has all the Iterators you ever need, and i’m not exaggerating at all. This includes iteratorfilters and many others. You can use this for example in you database results, making the DbResult object implement the Iterator interface, thus making functions such as next(), prev() and other available so you can iterate results in a foreach. Another good example for Iterators is traversing a directory. In the usual manner you can iterate over scandir, then use if and else to skip over “.”,  “..” and any other files, say for example you want just the pictures from a directory. You can do all this using iterators and iterator filters, like in this example:

    1 <?php
    2
    3 class RecursiveFileFilterIterator extends FilterIterator
    4 {
    5     protected $ext = array('jpg','gif');
    6
    7     /**
    8     * Takes $path and creates a recursive iterator with a directory iterator
    9     * @param $path diretory to iterate
   10     */
   11     public function __construct($path)
   12     {
   13         parent::__construct(new RecursiveIteratorIterator(new RecursiveDirectoryIterator($path)));
   14     }
   15
   16     /**
   17      * Checks extension names for files only.
   18      */
   19     public function accept()
   20     {
   21         $item = $this->getInnerIterator();
   22         if ($item->isFile() && in_array(pathinfo($item->getFilename(), PATHINFO_EXTENSION), $this->ext)) {
   23             return TRUE;
   24         }
   25     }
   26 }
   27
   28 // Using it
   29 foreach (new RecursiveFileFilterIterator('/path/to/something') as $item) {
   30     echo $item . PHP_EOL;
   31 }
   32
   33 ?>

You may argue that now you have much more code, I’ll reply: yes, but you have reusable and testable code!

Here are some more iterators:

  • RecursiveIterator
  • RecursiveIteratorIterator
  • OuterIterator
  • IteratorIterator
  • FilterIterator
  • RecursiveFilterIterator
  • ParentIterator
  • SeekableIterator
  • LimitIterator
  • GlobIterator
  • CachingIterator
  • RecursiveCachingIterator
  • NoRewindIterator
  • AppendIterator
  • RecursiveIteratorIterator
  • InfiniteIterator
  • RegexIterator
  • RecursiveRegexIterator
  • EmptyIterator
  • RecursiveTreeIterator
  • ArrayIterator

As of PHP 5.3 we have some other interesting tools, like SPLInt and other types you can use for type-casting. One class worth mencioning however is:

SplFixedArray

Why? Its faster! Why? aha! that’s the million dollar question. See to understand that we must delve into the PHP internals for a regular array. In a regular array you can use different types of keys, i.e. numeric, strings and so forth. What PHP does is that it does not use that value as a key in  the underlying C array, rather it hashes whatever it gets and uses that as a key, so hashing has a performance cost. SplFixedArray only accepts numeric keys, so no hashing happens! For those of you that caught up, yes, it is a C array! Which explains why this is faster than regular arrays. (only php5.3!!)

These are just some examples of what you can do with SPL, unfortunately there is no single place to go and get a complete view of SPL. You can hit the regular manual, but you should always trust in this documentation, done by the creators themselves, or you can hit Elizabeth’s Blog, most examples on this article belong to her.

Invitation

There is no better way to get better at SPL than contributing to it! We need documentators! So if you want to be part of PHP and help out, check out the php.doc mailing list, or IRC your way to EFNet and join #php.doc and say “I want to help”, you will be given a task very fast!

Related Posts

  1. Iterating with SPL 101: Directory Iterators
  2. New features of PHP 5.3

Tags: , ,

Rafael Dohms

PHP Warlock & Stuff Developer

A Zend Certified Engineer for PHP5 who loves going to conferences and doing sessions on PHP and related Technologies, as well as publishing articles on the same subjects. Passionate about the community he currently leads the PHPSP User Group and hosts a PHP podcast.
blog comments powered by Disqus