An Introduction to  SPL ,  
       the  S tandard  P HP  L ibrary 
      
     
      
       
      
     
      
       Robin Fernandes (  [email_address]  / @rewbs )

      
       What is SPL? 
       
       A collection of  classes and interfaces  for   solving  common programming problems . 
       
       
        
         
          
           
            
             Useful  data structures 
            
            
             Loads of  iterators 
            
            
             General-purpose  exception  hierarchy 
             
             & more...

      
       Why use SPL? 
       
        
         
          
           Helps you write  less code 
          
          
           Provides  reusable components 
          
          
           Provides  recognisable behaviour 
          
          
           It's relatively  fast 
          
          
           It's well  tested  (soon to be  extremely  well tested) 
           
          
         
        
       
       
      
     
      
       
       
       
       
       Zend 
       Framework 
      
     
      
       
      
     
      
       
       
       
       
       
       Agavi

      
       SPL Documentation 
       
        
         Some info here: 
         
          
           
            
             http://php.net/spl 
            
           
          
         
         
        
        
         More info here: 
         
          
           
            
             http://php.net/~helly 
            
           
          
         
         
        
        
         Also see PHP code in cvs: 
         
          
           
            
             ext/spl/examples/*.php, *.inc 
             ext/spl/internal/*.php, *.inc

      
       SPL Data Structures 
       
        
         
          
           In PHP 5.2 : 
           
            
             ArrayObject -> OO array wrapper – extend it! 
            
            
             SplObjectStorage -> Dictionary with objects as keys 
            
            
             SplFileObject -> OO stream wrapper 
            
           
          
          
           New in PHP 5.3 : 
           
            
             SplDoublyLinkedList 
            
            
             SplStack -> Last In First Out 
            
            
             SplHeap -> Binary heap 
             
              
               SplMaxHeap, SplMinHeap 
              
             
            
            
             SplQueue -> First In First Out 
            
            
             SplPriorityQueue 
            
            
             SplFixedArray -> aka SplFastArray: C array of zval

      
       Iterators 
       
        
         What's an Iterator? 
        
       
       An  iterator  implements a  consistent interface  for  traversing a collection . 
       
        
         
        
       
       
       
        
         Why Use Iterators? 
        
       
       Iterators  decouple collections from algorithms  by encapsulating traversal logic.

      
       Without Iterators 
      
     
      
       ... 
      
     
      
       ... 
      
     
      
       Algorithms: 
      
     
      
       ... 
      
     
      
       ... 
      
     
      
       ... 
      
     
      
       ... 
      
     
      
       ... 
      
     
      
       ... 
      
     
      
       Sum: 
      
     
      
       Average: 
      
     
      
       Display: 
      
     
      
       Collections: 
      
     
      
       
      
      
       1 
      
      
       2 
      
      
       3 
      
      
       4 
      
     
      
       1 
      
      
       4 
      
      
       5 
      
      
       3 
      
      
       2

      
       With Iterators 
      
     
      
       ... 
      
     
      
       Collections: 
      
     
      
       Algorithms: 
      
     
      
       ... 
      
     
      
       Iterators: 
      
     
      
       Algorithms are 
       decoupled 
       from collections! 
      
     
      
       
      
      
       1 
      
      
       2 
      
      
       3 
      
      
       4 
      
     
      
       1 
      
      
       4 
      
      
       5 
      
      
       3 
      
      
       2

      
       Iterators in PHP 
       
        
         To create your own iterator class, implement  Iterator : 
        
       
       
       
       
        
         
         
        
        
         To make a collection class iterable using a distinct iterator, implement  IteratorAggregate : 
        
       
      
     
      
       interface  Iterator  extends  Traversable { 
       function  rewind(); 
       function  valid(); 
       function  current(); 
       function  key(); 
       function  next(); 
       } 
      
     
      
       interface  IteratorAggregate  extends  Traversable { 
       function  getIterator(); 
       }

      
       Iterators in PHP 
       
      
     
      
       class  MyList 
       implements  IteratorAggregate { 
       
       private  $nodes  = ...; 
       
       
       function  getIterator() { 
       return new  MyListIterator( $this ); 
       } 
       
       } 
      
     
      
       class  MyGraph 
       implements  IteratorAggregate { 
       
       private  $nodes  = ...; 
       private  $edges  = ...; 
       
       function  getIterator() { 
       return new  MyGraphIterator( $this ); 
       } 
       
       } 
      
     
      
       function  show( $collection ) { 
       
       foreach  ( $collection  as  $node ) { 
       echo  &quot; $node <br/>&quot; ; 
       } 
       
       } 
      
     
      
       echo  show( new  MyList); 
      
     
      
       echo  show( new  MyGraph);

      
       Iterators in PHP 
       Traversable objects get  special foreach treatment : 
      
     
      
       foreach  ( $traversableObj  as  $key  =>  $value ) { 
       // Loop body 
       } 
      
     
      
       // 1. Get the Iterator instance from $traversableObj: 
       if  ( $traversableObj  instanceof  Iterator) { 
       $iterator  =  $traversableObj ; 
       }  else if  ( $traversableObj  instanceof  IteratorAggregate){ 
       $iterator  =  $traversableObj ->getIterator(); 
       } 
       
       // 2. Loop using the methods provided by Iterator: 
       $iterator ->rewind(); 
       while  ( $iterator ->valid()) { 
       $value  =  $iterator ->current(); 
       $key  =  $iterator ->key(); 
       // Loop body 
       $iterator ->next(); 
       } 
      
     
      
       <=> 
      
     
      
       …   is equivalent to   ... 
      
     
      
       Note: 
       
       
        
         - User-space classes can't implement Traversable directly. 
        
       
       
       - No class can implement both Iterator  and  IteratorAggregate.

      
       SPL Iterators 
       
      
     
      
       Iterator decorators: 
       AppendIterator 
       CachingIterator 
       FilterIterator 
       InfiniteIterator 
       IteratorIterator 
       LimitIterator 
       MultipleIterator  (5.3) 
       NoRewindIterator 
       ParentIterator 
       RegexIterator 
       RecursiveIteratorIterator 
       RecursiveCachingIterator 
       RecursiveFilterIterator 
       RecursiveRegexIterator 
       RecursiveTreeIterator  (5.3) 
      
     
      
       Concrete iterators: 
       ArrayIterator 
       RecursiveArrayIterator 
       DirectoryIterator 
       RecursiveDirectoryIterator 
       EmptyIterator 
       FilesystemIterator  (5.3) 
       GlobIterator  (5.3) 
      
     
      
       Unifying interfaces: 
       RecursiveIterator 
       SeekableIterator 
       OuterIterator

      
       More Iterators... 
       
        
         Many SPL data structures  implement Iterator 
         ->  They can be passed directly to decorators: 
         
         
         
        
        
         More iterators  implemented in PHP   in CVS: 
         
          
           ext/spl/examples/*.inc, *.php 
           For example:  callbackFilterIterator.inc 
           
            
             Implementation of FilterIterator which uses a callback (or closure) as the filter function. 
            
           
          
         
        
       
      
     
      
       $s  =  new  SplStack(); 
       $i  =  new  InfiniteIterator ( $s ); 
       $s ->push( 1 );  $s ->push( 2 );  $s ->push( 3 ); 
       foreach  ( $i  as  $v ) { 
       echo  &quot; $v  &quot; ;  //3 2 1 3 2 1 3 2 1 3 2... 
       }

      
       A Note on Recursive Iterators... 
       
        
         This doesn't work: 
         
         
        
        
         Try this instead: 
         
         
         
         
          
           RecursiveFilterIterator, RecursiveDirectoryIterator etc...  implement  recursive behaviour but  do not exploit it . 
           
            
             ->  Perhaps they should be called   “recursible”   iterators? 
            
           
          
          
           A  RecursiveIteratorIterator  wraps a “recursible” iterators and  exploits  its recursive behaviour. 
          
         
        
       
      
     
      
       $a  =  array ( 1 ,  2 ,  array ( 3 ,  4 )); 
       $i  =  new  RecursiveArrayIterator( $a ); 
       foreach  ( $i  as  $v ) {  echo  &quot; $v  &quot; ; }  // 1 2 Array 
      
     
      
       $a  =  array ( 1 ,  2 ,  array ( 3 ,  4 )); 
       $i  =  new  RecursiveArrayIterator( $a ); 
       $i  =  new  RecursiveIteratorIterator ( $i ); 
       foreach  ( $i  as  $v ) {  echo  &quot; $v  &quot; ; }  // 1 2 3 4

      
       SPL Iterators 
       
      
     
      
       Iterator decorators: 
       AppendIterator 
       CachingIterator 
       FilterIterator 
       InfiniteIterator 
       IteratorIterator 
       LimitIterator 
       MultipleIterator  (5.3) 
       NoRewindIterator 
       ParentIterator 
       RegexIterator 
       RecursiveIteratorIterator 
       RecursiveCachingIterator 
       RecursiveFilterIterator 
       RecursiveRegexIterator 
       RecursiveTreeIterator  (5.3) 
      
     
      
       Concrete iterators: 
       ArrayIterator 
       RecursiveArrayIterator 
       DirectoryIterator 
       RecursiveDirectoryIterator 
       EmptyIterator 
       FilesystemIterator  (5.3) 
       GlobIterator  (5.3) 
      
     
      
       Unifying interfaces: 
       RecursiveIterator 
       SeekableIterator 
       OuterIterator

      
       SPL Exceptions 
      
     
      
       
      
     
      
       
        
         SPL exceptions provide no extra logic or behaviour. 
        
       
       
       
        
         Each one is associated with a scenario  by convention . 
        
       
       
       
        
         Extend them to  specialize them for your domain . 
        
       
       
        
         
        
       
       Benefits: 
       -> Improve  consistency of exception use  within & across projects. 
       
       -> Increase the  self-documenting  nature of your code.

      
       More SPL Stuff... 
       
        
         Observer Pattern 
         
          
           Simple interfaces: SplObserver, SplSubject 
          
         
        
        
         Autoload Enhancements 
         
          
           Default autoloader with extension filtering 
          
          
           Define and chain custom autoload callbacks 
          
         
        
        
         Utility Functions 
         
          
           iterator_apply () , iterator_count () , iterator_to_array () 
          
          
           class_implements () , class_parents () 
          
          
           spl_object_hash ()

      
       Testing SPL 
       
        
         Great way to  learn (more) about SPL ! 
         
        
        
         See current  code coverage : 
         
          
           http://gcov.php.net/PHP_5_3/lcov_html/spl 
           
            
             
            
           
          
         
        
        
         All tests are valuable! 
         
          
           
            
             Tests for  basic functionality 
            
            
             Tests for  interesting edge cases

      
       Come to TestFest! 
       
        
         Saturday 9 th  May 2009 @ IBM SouthBank 
        
       
       
       
        
         
          
           
            
             Never used SPL? Come to learn! 
            
            
             Already know SPL? Come to to dig deeper! 
            
            
             Make PHP better! 
            
            
             Get kudos! 
            
            
             Win an elephpant!

      
       Iterators – bonus 
       What's this Traversable interface all about? 
       
        
         Iterator and IteratorAggregate  both extend Traversable . 
        
        
         Traversable is a  marker interface  (it does not provide any methods). 
        
        
         It is  used internally by the engine  to detect iterability.  
        
        
         It  cannot be implemented directly from PHP code  – only indirectly, via Iterator and IteratorAggregate 
        
        
         But it  can  be implemented directly by  internal classes  to provide limited iterability,  without implementing the full Iterator interface . 
        
        
         Few people need worry about it.

An Introduction to SPL, the Standard PHP Library

  • 1.
    An Introduction to SPL , the S tandard P HP L ibrary Robin Fernandes ( [email_address] / @rewbs )
  • 2.
    What is SPL? A collection of classes and interfaces for solving common programming problems . Useful data structures Loads of iterators General-purpose exception hierarchy & more...
  • 3.
    Why use SPL? Helps you write less code Provides reusable components Provides recognisable behaviour It's relatively fast It's well tested (soon to be extremely well tested) Zend Framework Agavi
  • 4.
    SPL Documentation Some info here: http://php.net/spl More info here: http://php.net/~helly Also see PHP code in cvs: ext/spl/examples/*.php, *.inc ext/spl/internal/*.php, *.inc
  • 5.
    SPL Data Structures In PHP 5.2 : ArrayObject -> OO array wrapper – extend it! SplObjectStorage -> Dictionary with objects as keys SplFileObject -> OO stream wrapper New in PHP 5.3 : SplDoublyLinkedList SplStack -> Last In First Out SplHeap -> Binary heap SplMaxHeap, SplMinHeap SplQueue -> First In First Out SplPriorityQueue SplFixedArray -> aka SplFastArray: C array of zval
  • 6.
    Iterators What's an Iterator? An iterator implements a consistent interface for traversing a collection . Why Use Iterators? Iterators decouple collections from algorithms by encapsulating traversal logic.
  • 7.
    Without Iterators ... ... Algorithms: ... ... ... ... ... ... Sum: Average: Display: Collections: 1 2 3 4 1 4 5 3 2
  • 8.
    With Iterators ... Collections: Algorithms: ... Iterators: Algorithms are decoupled from collections! 1 2 3 4 1 4 5 3 2
  • 9.
    Iterators in PHP To create your own iterator class, implement Iterator : To make a collection class iterable using a distinct iterator, implement IteratorAggregate : interface Iterator extends Traversable { function rewind(); function valid(); function current(); function key(); function next(); } interface IteratorAggregate extends Traversable { function getIterator(); }
  • 10.
    Iterators in PHP class MyList implements IteratorAggregate { private $nodes = ...; function getIterator() { return new MyListIterator( $this ); } } class MyGraph implements IteratorAggregate { private $nodes = ...; private $edges = ...; function getIterator() { return new MyGraphIterator( $this ); } } function show( $collection ) { foreach ( $collection as $node ) { echo &quot; $node <br/>&quot; ; } } echo show( new MyList); echo show( new MyGraph);
  • 11.
    Iterators in PHP Traversable objects get special foreach treatment : foreach ( $traversableObj as $key => $value ) { // Loop body } // 1. Get the Iterator instance from $traversableObj: if ( $traversableObj instanceof Iterator) { $iterator = $traversableObj ; } else if ( $traversableObj instanceof IteratorAggregate){ $iterator = $traversableObj ->getIterator(); } // 2. Loop using the methods provided by Iterator: $iterator ->rewind(); while ( $iterator ->valid()) { $value = $iterator ->current(); $key = $iterator ->key(); // Loop body $iterator ->next(); } <=> … is equivalent to ... Note: - User-space classes can't implement Traversable directly. - No class can implement both Iterator and IteratorAggregate.
  • 12.
    SPL Iterators Iterator decorators: AppendIterator CachingIterator FilterIterator InfiniteIterator IteratorIterator LimitIterator MultipleIterator (5.3) NoRewindIterator ParentIterator RegexIterator RecursiveIteratorIterator RecursiveCachingIterator RecursiveFilterIterator RecursiveRegexIterator RecursiveTreeIterator (5.3) Concrete iterators: ArrayIterator RecursiveArrayIterator DirectoryIterator RecursiveDirectoryIterator EmptyIterator FilesystemIterator (5.3) GlobIterator (5.3) Unifying interfaces: RecursiveIterator SeekableIterator OuterIterator
  • 13.
    More Iterators... Many SPL data structures implement Iterator -> They can be passed directly to decorators: More iterators implemented in PHP in CVS: ext/spl/examples/*.inc, *.php For example: callbackFilterIterator.inc Implementation of FilterIterator which uses a callback (or closure) as the filter function. $s = new SplStack(); $i = new InfiniteIterator ( $s ); $s ->push( 1 ); $s ->push( 2 ); $s ->push( 3 ); foreach ( $i as $v ) { echo &quot; $v &quot; ; //3 2 1 3 2 1 3 2 1 3 2... }
  • 14.
    A Note on Recursive Iterators... This doesn't work: Try this instead: RecursiveFilterIterator, RecursiveDirectoryIterator etc... implement recursive behaviour but do not exploit it . -> Perhaps they should be called “recursible” iterators? A RecursiveIteratorIterator wraps a “recursible” iterators and exploits its recursive behaviour. $a = array ( 1 , 2 , array ( 3 , 4 )); $i = new RecursiveArrayIterator( $a ); foreach ( $i as $v ) { echo &quot; $v &quot; ; } // 1 2 Array $a = array ( 1 , 2 , array ( 3 , 4 )); $i = new RecursiveArrayIterator( $a ); $i = new RecursiveIteratorIterator ( $i ); foreach ( $i as $v ) { echo &quot; $v &quot; ; } // 1 2 3 4
  • 15.
    SPL Iterators Iterator decorators: AppendIterator CachingIterator FilterIterator InfiniteIterator IteratorIterator LimitIterator MultipleIterator (5.3) NoRewindIterator ParentIterator RegexIterator RecursiveIteratorIterator RecursiveCachingIterator RecursiveFilterIterator RecursiveRegexIterator RecursiveTreeIterator (5.3) Concrete iterators: ArrayIterator RecursiveArrayIterator DirectoryIterator RecursiveDirectoryIterator EmptyIterator FilesystemIterator (5.3) GlobIterator (5.3) Unifying interfaces: RecursiveIterator SeekableIterator OuterIterator
  • 16.
    SPL Exceptions SPL exceptions provide no extra logic or behaviour. Each one is associated with a scenario by convention . Extend them to specialize them for your domain . Benefits: -> Improve consistency of exception use within & across projects. -> Increase the self-documenting nature of your code.
  • 17.
    More SPL Stuff... Observer Pattern Simple interfaces: SplObserver, SplSubject Autoload Enhancements Default autoloader with extension filtering Define and chain custom autoload callbacks Utility Functions iterator_apply () , iterator_count () , iterator_to_array () class_implements () , class_parents () spl_object_hash ()
  • 18.
    Testing SPL Great way to learn (more) about SPL ! See current code coverage : http://gcov.php.net/PHP_5_3/lcov_html/spl All tests are valuable! Tests for basic functionality Tests for interesting edge cases
  • 19.
    Come to TestFest! Saturday 9 th May 2009 @ IBM SouthBank Never used SPL? Come to learn! Already know SPL? Come to to dig deeper! Make PHP better! Get kudos! Win an elephpant!
  • 20.
    Iterators – bonus What's this Traversable interface all about? Iterator and IteratorAggregate both extend Traversable . Traversable is a marker interface (it does not provide any methods). It is used internally by the engine to detect iterability. It cannot be implemented directly from PHP code – only indirectly, via Iterator and IteratorAggregate But it can be implemented directly by internal classes to provide limited iterability, without implementing the full Iterator interface . Few people need worry about it.