SPL - the Standard PHP Library - has some of the most useful tools you can find in PHP5. From interfaces to an autoload stack to classes that make objects act like arrays, there are tools to make every application leaner and faster, or simply more clever. This is a hands on, learn by doing adventure through the tools available in SPL. Start with exceptions, the autoload stack, and iterator helper functions. Learn how to use built in iterators and write your own. Journey through the new 5.3 data structures additions and get a little computer science lesson on the way. Add standard interfaces to make your event based programming easy to spot, and finally learn to use PHP's filesystem objects (that you probably didn't know existed)Who am I, and why should you listen to me?Windows buildsCairo, PHP-Gtk, Win\\GuiUsing PHP since php 4 betaHow I got involved in PHP community and why you should tooHow I got interested in spl – was the autoload stack and arrayobject that attracted me, but iterators that made me stay
This talk is not “what is in spl”This is not a beginners talk – but it’s also not really advancedI intend to talk about the how and why of using splevery single example I’m going to show comes from githubI’ll repeat that – all the code I will show you is code “in the wild”This is very much a use case and code romp through PHP landAsk what the audience is wanting to do? Also this is the QR code for join.in – leave me feedback – good bad or otherwise so I can improve my talks
So what exactly is SPL? What is in it? Why should you careDon’t write userland code for stuff that already exists in PHPWould you write an http_build_query (oh wait) or how about your own implode? If the stuff exists in PHP USE ITEngine overloading hooks via interfacesSerialize, ArrayAccess, Countable, IteratorsClasses that utilize the hooks to make life easierArrayObject, RecursiveIterator, DirectoryIteratorStandard Class ImplementationsExceptions, SplObserver and SplStorageFunctions to help with autoloading and objectsspl_autoload_register(), spl_classes(), iterator_apply()5. Advanced data structures
SPL is like date or standard or pcre – if those are turned off you do NOT have PHP, you have troubleI can’t depend on an extension that might not be presentUm… if spl is not present – urdoin it rong
Lets start at the very beginning with the most useful and the most widely used functionality in PHP, that of autoloadingSpl has a suite of autoloading functions – namely the autoload stack functionality plus it’s own implementation of a simple autoloading functionspl_autoload_call — Try all registered __autoload() function to load the requested classspl_autoload_extensions — Register and return default file extensions for spl_autoloadspl_autoload_functions — Return all registered __autoload() functionsspl_autoload_register — Register given function as __autoload() implementationspl_autoload_unregister — Unregister given function as __autoload() implementationspl_autoload — Default implementation for __autoload()Php’s own __autoload support is short sighted and can cause a LOT of conflict when you start using any third party librariesIt’s far more fun (and less painful) to just use the autoload stack
How to use the stackpush on with register,yank off with unregister (NOTE: you need to have the same callback used to pull it back off, this might get hairy with object method callbacks or closures!) – that’s where the autoload functions can come in handyThese are your basic stack mechanisms – remove and item, add an item, get all items – try to load a class using the current stackI’m not going to show examples of how to use these because it’s pretty braindead and EVERYONE uses this, you can find examples for doing autoload all over the internetHowever some caveats to remember – Functions are called in FIFO – you can’t prepend items on the stack until 5.3, that second parameter? throw exceptions? that means throw an exceptions if the registration of the callback failedI’m not going to show you code using this – because autoloading using spl_autoload_register is the way of doing autoloading in PHPEVERYBODY uses it from PEAR to ZF2 – heck even ZF1 can be used with it. Go do a codesearch at like google or github and you’ll see what I meanBut this is one of the coolest uses of a more “esoteric” autoload stack function that I’ve seenThis allows you to avoid “incomplete class” issues with your code, while using the ENTIRE CURRENT AUTOLOAD STACK – yeah, really awesome there (everyone – do this in your code – seriously)PSR-0 says “use this” so “use this use this”
Beware of spl_autoload – By default it checks all include paths to contain filenames built up by the lowercase class name appended by the filename extensions .inc and .php. it’s also aware of namespaces and looks for directoriesnote, it’ll drive APC nuts, since it uses relative paths “internally”note it lower cases stringsnote it looks for .php and .inc by default (you can adjust this)There’s a reason nobody really uses the default autoload function and I would highly recommend you don’t use it either
Everyone and their mother uses spl_autoload_registerAlthough there are no SOLID plans for deprecating __autoload, do not do do not do do not do
Ask how many prefer exceptions for error handling in their codeAsk how many prefer to know a little bit more data then what php gives?Whats the general type of information that you want to know?I like to know 1. the “domain” of what went wrong and 2. the “type” of what went wrongBut remember exceptions are for “exceptional situations” and aren’t really appropriate for everythingAlso there are two ways of doing exceptions – subclassing by library/component and subclassing by action – personally I prefer the exception interface for component, and the subclassing by more information for exceptions
Anything that could have been detected at compile time, during application design, or by careful code reviewPerfect for libraries to tell your consumer “you’re being stupid”Exception that represents error in the program logic. This kind of exception should directly lead to a fix in your code. Exception that represents error in the program logic. This kind of exception should directly lead to a fix in your code.This is in fact a best practice: Always throw a BadMethodCallException when you create a __call method! Otherwise your code could be calling functions which indeed don’t exist, and you never know about it (for example if you have typed the name wrong).That invalid argument exception? Yeah, use that… a lotSubclass that for your stuff!You could argue that the three on the left are reallytheir own little groupThe dynamic call group contains the exceptions BadFunctionCallException and BadMethodCallException. BadMethodCallException is a subclass of BadFunctionCallException which in turn is a subclass of LogicException.
Anything that is unexpected during runtimeThis is for cases where an error happens that could only be detected while the program is running. The naming is a holdover from compiled languages, where certain errors can be detected at compile timeRalph Schindler has a really excellent article on exceptions and how to do them right, and how to pick which of these to use
Catch your exceptions at the component level with a marker – since the exception won’t have anything else in common with the rest of the code but the “domain” – the package, library, whatever. And since interfaces can extend interfaces you can chain up your marker interface AND chain up your logic exceptionZF2 does this VERY well
I ’M AN ARRAY, WELL KIND OF BUTI’M AN OBJECT, REALLY!I AM INCREDIBLY USEFULThere are several interfaces that make objects have behavior like arraysCountableArrayaccess ()Iterator (iteratoraggregate actually)SerializableAlthough it would be nice to say “well let’s just pass in anything implementing arrayaccess and have it work” that has some serious holes to itNative PHP arrays have a concept of “order” – well cause they’re not really arrays but that’s another story
ArrayObject::append — Appends the valueArrayObject::asort — Sort the entries by valueArrayObject::exchangeArray — Exchange the array for another one.ArrayObject::getArrayCopy — Creates a copy of the ArrayObject.ArrayObject::getFlags — Gets the behavior flags.ArrayObject::ksort — Sort the entries by keyArrayObject::natcasesort — Sort an array using a case insensitive "natural order" algorithmArrayObject::natsort — Sort entries using a "natural order" algorithmArrayObject::setFlags — Sets the behavior flags.ArrayObject::set(get)IteratorClass — Sets the iterator classname for the ArrayObject.ArrayObject::uasort — Sort the entries with a user-defined comparison function and maintain key associationArrayObject::uksort — Sort the entries by keys using a user-defined comparison function
SPL has a set of interfaces that “make magic” – note:
These are actually part of PHP core, not SPL as many people believe but I’ll run over them a bit… they are EVERYWHERE (except traversable, which is not implementable in userland)Traversable means “can be iterated but doesn’t have the method signatures” – pdo stuff falls in this spotIterator – rewind, valid, current, key, nextIteratoraggregate – I’ve got me an iterator in my iteratorArrayaccess – like object overloading but with array syntax – offsetGetoffsetSetoffsetUnsetoffsetIssetYou can return by reference in offsetGet as of PHP 5.3.4!!Serializable – serialize/unserializegimme string, get me stringClosure – super secret special – __invoke is evil
These are actually part of PHP core, not SPL as many people believe but I’ll run over them a bit… they are EVERYWHERE (except traversable, which is not implementable in userland)Traversable means “can be iterated but doesn’t have the method signatures” – pdo stuff falls in this spotIterator – rewind, valid, current, key, nextIteratoraggregate – I’ve got me an iterator in my iteratorArrayaccess – like object overloading but with array syntax – offsetGetoffsetSetoffsetUnsetoffsetIssetYou can return by reference in offsetGet as of PHP 5.3.4!!Serializable – serialize/unserializegimme string, get me stringClosure – super secret special – __invoke is all you need anyway
Iterator count actually walks the iterator and gets the number of valid entriesCount can be implemented to be anything appropriate for what you’re writing – it may have nothing to do with what you iterate over
OuterIterator (interface)Extends IteratorPuts a wrapper around an iterator insideHas one additional method – getInnerIterator() that should be implementedRecursiveIterator (interface)Has two additional methods to implementgetChildren should return the sub-iterator for the current element – and it must return an object that implements recursiveIteratorhasChildrenSeekableIterator (interface)Additional method – seek(string $position)Lets you jump to a specific spot to start iterating
Abstract classes for anything using an observer pattern- great common sense tutorialIf you do event/observers in your code, extending these two makes good sense
PHP arrays discussion – PHP arrays are an ordered hashtableWhile great for general use cases, you might run into situations where you need moar
n computer science, a list is defined as an ordered collection of values. A linked list is a data structure in which each element in the list includes a reference to one or both of the elements on either side of it within the list. The term “doubly-linked list” is used to refer to the latter case. In the SPL, this takes the form of the class SplDoublyLinkedList.
This class is in spl for one reason only – it’s the base for several other HIGHLY USEFUL classes I’ll be talking about later – it’s main use, really it’s only use is as a parent class with the base functionality that other datastructures are built off of.
Ahhh, now we’re getting to something useful!LIFO – last in, first outyou push or shift items onto the stack and pop or unshift them offbut notice you must access items sequentiallythe stack name is a misnomer, this is not really a stack in the pure CS sense – it’s a double link list that likes to go backward!and there’s a weird performance issue with it too
this is the opposite of splstack – same base class, same underlyign storage mechanism – the difference here of course is the direction
NOTE: there are other “heaps” in computer science – the datastructure with comparison fucntion is the one we’re usingIn computer science, a heap is a specialized tree-based data structure that satisfies the heap property: if B is a child node of A, then key(A) ≥ key(B). This implies that an element with the greatest key is always in the root node, and so such a heap is sometimes called a max-heap. (Alternatively, if the comparison is reversed, the smallest element is always in the root node, which results in a min-heap.) The maximum number of children each node can have depends on the type of heap, but in many types it is at most two. The heap is one maximally efficient implementation of an abstract data type called a priority queue. Heaps are crucial in several efficient graphalgorithms such as Dijkstra's algorithm, and in the sorting algorithm heapsort.
Only the root element of a heap, the one yielding the highest comparison function return value, may be accessed or removed from the heap at any given time.At first glance, using a subclass of SplHeap may seem equivalent to calling sort() or a similar function on an array and accessing the elements in sequence. This is indeed the case if all elements are added to the array prior to it being sorted. However, situations such as elements arriving over time or inadequate memory to store all elements simultaneously may preclude this approach. Use of arrays in such situations would require repeated resorting of the entire array as new elements are added, which is inefficient. This is why using the corresponding heap class makes a lot more sense in that situation than repeated calls to sort(), min() or max(). Additionally, SplHeap can be used to implement the heapsort algorithm, which has better worst case performance than the quicksort algorithmimplementationused by arrays.
The maxheap is more of an exampleHowever something to think about – splpriorityqueue IS actually a maxheap (not really a queue… which is wtfy)Second is a A* pathfinding implementation in PHP ;)In computer science, A* (pronounced "A star" ( listen)) is a computer algorithm that is widely used in pathfinding and graph traversal, the process of plotting an efficiently traversable path between points, called nodes.
In fact, while it doesn’t extend SplHeap, SplPriorityQueue does make use of a heap structure internally to implement its functionality. The difference is that the insert() method of SplPriorityQueue queue accepts both a value and an associated priority, removing the need to use an array or object to store both of these and define an appropriate comparison function in an SplHeap instance. Elements with the highest priority, like those in SplMaxHeap with the highest value, are the ones that come out first when extract() is called. Note that elements with equal priority are returned in no particular order.For reasons similar to those of SplHeap, SplPriorityQueue implements both Iterator and Countable interfaces and does not implement the ArrayAccess interface. Because it stores a value and priority per element, SplPriorityQueue includes a setExtractFlags() method that modifies the behavior of extract() to return the stored value, the stored priority, or an array containing both. Priorities are not bound to a particular data type: strings, integers, or even composite data types can be used. SplPriorityQueue can be extended and its compare() method overridden to customize the comparison logic.
The SplFixedArray class provides the main functionalities of array. The main differences between a SplFixedArray and a normal PHP array is that the SplFixedArray is of fixed length and allows only integers within the range as indexes. The advantage is that it allows a faster array implementation. Memory footprint of splFixedArray is about 37% of a regular "array" of the same sizeNOTE: This only affects CREATION time, NOT access time.This really needs to be a case by case basis if this is the right solution – one thing I HAVE used it for myself is for data coming back from databases in large chunks I’m going to iterate over – chucking it into a fixed array since I already know the windowing size is GREATYou can use this basically anywhere you would use arrayobject, has the same sorts of limitations – only you get better creation speed and memory footprin
it provides the same functionality of a hash table that a normal array has, but without its associated inability to use objects as keys unless the spl_object_hash() function is used. In other words, it implements a composite hash map. Second, it can be used as a set to store objects as data without a meaningful corresponding key or concept of sequential order
A design pattern that is a generic solution to the problem of iterating over data in a consistent manner.Access the elements of an aggregate object sequentially without exposing its underlying representation.Readable Easy to understand Testable Easy to refactor Consistent usageEasily add functionalityCan be extendedCan be chained
Warning – this might have unintended consequencesHere’s a hint – pdostatement implements traversable
this Iterator can manage both native PHP arrays and the public properties of an objectI see this a lot for things like collections, child nodes, etc.
An Iterator that iterates over several iterators one after the other.
Incredibly clever use to get part of a file ;)
this manages another Iterator (which you pass to its constructor). It allows you to check whether the inner Iterator has more elements, using the hasNext() method, before actually advancing with the next() method. Personally, I'm not 100% sure about the name; perhaps LookAheadIterator would be more accurate?
This is an AWESOME iterator – stick a directory or glob iterator in here and have a great time
this is largely the same as the CachingIterator, but allows iteration over hierarchical data structures.the name; perhaps LookAheadIterator would be more accurate?
This is an AWESOME iterator – stick a directory or glob iterator in here and have a great time
Parentiterator - This extended FilterIterator allows a recursive iteration using RecursiveIteratorIterator that only shows those elements which have children. NoRewindIterator – calling rewind does not error… but also does nothingMultipleIterator - An Iterator that sequentially iterates over all attached iterators CallbackFilterIterator — The CallbackFilterIterator class – implements filter iterator with a callback – don’t be lazy with this!RecursiveCallbackFilterIterator — The RecursiveCallbackFilterIterator classGlobIterator — Iterate over a filesystem using glob (extends filesystemiterator)
quick roundabaout with what people want to see implemented in spl, get some ideas of things they’re missingI want –Strict structsenumsreal sets for things other then objectsRenaming (caching iterator is so misnamed/misfeatured)A real doubly linked list…
So how do you spread the word and help make streams sockets and filters something to be used more “in the wild”First of all, the documentation can always use a hand, visit edit.php.net for an online docbook editor to add stuff to the manualCode samples and blog posts and articles are also a good good thingBut most of all get your own applications using it and showcasing the cool opportunities for this kind of stuffI know ZF2 and syfony 2 and some of the other newer frameworks are really making use of cool stuff in spl, use it, don’t reinvent the wheel
Let’s wrap it up and wake up
Spl in the wild - zendcon2012
SPL IN THE WILDThe Good, the Bad and the Ugly
NOT A BEGINNERS TALK!If you don’t know SPL basics, this talk might go fast for you.Please rate me – https://joind.in/7394
Why SPL?What SPL?How SPL? A library of standard interfaces, classes, and functions designed to solve common programming problems and allow engine overloading
BUT ISN’T SPL AN EXTENSION? SPL is an extension SPL is a core extension SPL cannot be built shared SPL should not be turned off SPL is present in PHP since 5.0 (almost 5 years ago) As of 5.3, SPL cannot be turned off If you don’t have SPL, whoever built your PHP is an idiot.
SPLFILEINFO Metadata about a file Returned by directory iterators Can set your own superclass for splfileinfo/splfileobject In the Wild phpcmc https://github.com/fqqdk/phpcmc/blob/master/tes ts/phpcmc/micro/PhpLinterTest.php#L40
SPLFILEOBJECT Open file pointer Extends splfileinfoIn the Wild Utils Plugin for CakePHP https://github.com/CakeDC/utils/blob/master/ Model/Behavior/CsvImportBehavior.php#L68
SPECIFICALLY ARRAYOBJECT Implements ArrayAccess (with references) Implements Countable Implements IteratorAggregate Implements Serializable (since 5.3.0) And other methods that arrays can use (but not all) In the Wild Rapide Framework https://github.com/Hanse/rapide- framework/blob/master/lib/Rapide/Utility/ArrayObject.php# L13
MORE CORE INTERFACESArrayAccess https://github.com/opensky/symfony/blob/025d41c14999fbc32a1f7b282ea920 129cad529d/src/Symfony/Component/Form/Form.php#L748Serializable https://github.com/shizzard/RAPIClient/blob/master/Helper/Storage.p hp#L276JsonSerializable https://github.com/sebastianbergmann/psonClosure Do not use (seriously)
SPL - COUNTABLE Interface meaning “you can count me” Can be put on any class Makes count() magical Note this is NOT the same as iterator_count() https://github.com/ysbaddaden/php5- redis/blob/master/lib/Redis/Servers.php#L9
ITERATOR INTERFACES Outer Iterator Inner Iterator Seekable Iterator For examples, we’ll look at the iterator classes
SPLSUBJECT SPLOBSERVER Are you implementing the observer pattern in your code? Do you intend to have other people use your code/library in some way? Are you implementing something LIKE the observer pattern? In the Wild EmailLabs_Sync https://github.com/sankovicmarko/EmailLabs_Sync/blob/master/librar y/EmailLabs/Logger.php#L93 Vih.dk https://github.com/vih/vih.dk/blob/2348af482b2fc78753513dbf94330c 13d5d1f69f/src/VIH/ExceptionHandler.php#L40
DOUBLYLINKEDLISTS – CSLESSON ordered collection of values linked to each element before it linked to each element after it “doubly linked” PHP datastructure – a php object with a doublylinkedlist stored inside it
SPLDOUBLYLINKEDLIST Don’t use this Yes, that’s a terrible thing to say – but this is really nothing more then a “base class” with little to recommend on its own Has a doublylinkedlist from C underneath instead of a hashtable – if you know what that means you may find a real use for this (I have not) https://github.com/osebboy/Notification/blob/master/src/Notificatio n/Dispatcher.php#L111
SPLSTACK Data is in LIFO Anything you need to iterate a lot Even cooler? Turn on the mode that will autodelete each item as you process it Any Queue you need to push stuff onto and deal with in LIFO order https://github.com/rsesek/phalanx/blob/master/tasks/task_pump.p hp#L54
SPLQUEUE Data is in FIFO Anything you need to iterate a lot Even cooler? Turn on the mode that will autodelete each item as you process it Any Queue you need to push stuff onto and deal with in LIFO order https://github.com/matthewshafer/fauxThread/blob/master/src/fau xThreadPool.php#L28
HEAP – QUICK CS LESSON comparison function used to compare the new element to other elements element is placed according to functions return value underlying algorithm does it with minimal comparisons PHP datastructure – a php object with a heap stored inside it
USING SPLHEAP This is an abstract class You need to compare elements https://github.com/ckwalsh/LibSprite https://github.com/ckwalsh/LibSprite/blob/master/src/php5_3/CKW alsh/LibSprite/Util/Block/Heap/Width.php#L15 https://github.com/ckwalsh/LibSprite/blob/master/src/php5_3/CKW alsh/LibSprite/Packer/GreedyHeap.php#L16
SPLMINHEAP, SPLMAXHEAP These are concrete heap implementations, designed to grab the lowest possible value out, or the highest possible https://github.com/tobyS/php- snippets/blob/master/datastructures/bottom_k.php#L44 https://github.com/stormbreakerbg/A---A-Star--pathfinding-class- in-PHP/blob/master/AStarWithHeap.php#L196
SPLPRIORITYQUEUE Uses heap internally Is non-deterministic when identical priorities are used https://github.com/ss23/DeBot/blob/master/core/SplFIFOPriorityQ ueue.php#L16
SPLFIXEDARRAY You have a large amount of data, you know the final size, you need to stick it into an array You’re not going to expand it past the final size This is not a small amount of data You might need it in non-sequential order but can handle having only integers for keys https://github.com/cboden/gClient/blob/master/lib/gClient/Calenda r/Calendar.php#L83
SPLOBJECTSTORAGEThis can be used two ways Objects can be keys in an array (with two values) As a Set (with one value) https://github.com/greggles/epm_project_management/blob/mast er/QueryPath/CssEventHandler.php#L17
(RECURSIVE)FILTERITERATOR Abstract Class Has one method that must be implemented – accept – which should return true or false Highly useful for many types of iteration https://github.com/nishimura/laiz/blob/master/laiz/builder/AutoIncl udeFilter.php https://github.com/ralphschindler/PHPTools/blob/master/library/PH PTools/Namespacer/RecursiveFilterIterator.php FilterIterator OuterIterator Iterator Traversable
(RECURSIVE)ITERATORITERATOR Regular Class Stick in something that implements traversable Instant Iterator https://github.com/halfnelson/LINQ4PHP/blob/master/Iterators/Tra nsformIterator.php https://github.com/symfony/symfony/blob/master/src/Symfony/Co mponent/Finder/Iterator/DepthRangeFilterIterator.php IteratorIterator OuterIterator Iterator Traversable
(RECURSIVE)ARRAYITERATOR Regular Class Iterates an array – OR the public properties of an object! (neat trick – dirty trick) https://github.com/diggin/Diggin_Service_Wedata/blob/master/src/ Diggin/Service/Wedata/Items.php https://github.com/Respect/Validation/blob/master/library/Respect/ Validation/ExceptionIterator.php ArrayAccessArrayIter Seekabl Traversabl and Iterator e Countable ator eIterator too!
APPENDITERATOR Keep stacking more iterators on the end with append https://github.com/WebToad/FashionPolice/blob/master/libs/Nette/ Utils/Finder.php ParentIterator OuterIterator Iterator Traversable
LIMITITERATOR Regular Class Like mysql’s limit – pick your range and offset and foreach away! https://github.com/jasir/ComponentTreePanel/blob/master/Compo nentTreePanel.phpp#L187 LimitIterator OuterIterator Iterator Traversable
FILESYSTEMITERATOR Extends directory iterator Lets you choose how to get data (just string names possible) https://github.com/gplanchat/php- git/blob/d502926d5b22a4081a9efffd60dbb1b8094908c0/library/Gi t/AdapterAbstract.php FileSystemIterator DirectoryIterator Iterator Traversable
(RECURSIVE)CACHINGITERATOR Regular Class Manages another iterator by checking whether it has more elements each time using a hasNext() method https://github.com/bshaffer/Donate- Nashville/blob/master/plugins/sfPhpExcelPlugin/lib/PHPExcel/PH PExcel/Worksheet/RowIterator.php CachingIterator OuterIterator Iterator TraversableRecursiveCa CachingIterator OuterIterator Iterator TraversablechingIterator
(RECURSIVE)DIRECTORYITERATOR Regular Class Walk a Directory https://github.com/quentinhill/curator/blob/master/Curator/Project. php#316 https://github.com/spidee/PHP- Framework/blob/master/libs/Smarty/sysplugins/smarty_internal_ut ility.php#66 DirectoryIterator SplFIieInfo Iterator Traversable RecursiveDirectoryIteerator DirectoryIterator
RECURSIVETREEITERATOR Regular Class Can create an ascii graphic tree (seriously…) https://github.com/Respect/Validation/blob/master/library/Respect/ Validation/Exceptions/AbstractNestedException.php#58RecursiveT RecursiveIter OuterIterator Iterator TraversablereeIterator atorIterator
(RECURSIVE)REGEXITERATOR Regular Class Filter an iterator by a regex Pick how you want it to match https://github.com/lgunsch/victorycms- core/blob/master/lib/utilities/Vcms-FileUtils.php#L144 RegexIterator FilterIterator Iterator Traversable RecursiveRegexIteerator RegexIterator
EMPTY AND INFINITE ITERATORS In the Wild – EmptyIterator https://github.com/evilgeny/bob/blob/master/romir/projects/libraries/Barcode/M apper.class.php#L680 Infinite? Really only useful for testing EmptyIterator Iterator Traversable InfiniteIterator IteratorIterator Iterator Traversable
MORE EXIST ParentIterator NoRewindIterator MultipleIterator GlobIterator CallbackFilterIterator RecursiveCallbackFilterIterator
WHAT DO YOU WANT TO SEE INSPL?More standard interface?More datastructures? trees? graphs?More iterators? really? more?
GET INVOLVEDhttp://edit.php.netBlog postsArticlesUse SPL in the wild