什麼是SPL?php
通俗點講SPL就是一套PHP 自帶的標準的類與接口的集合,使用它來處理一些平常事務 如遍歷文件目錄,遍歷數組,資源類型數據,效率上講會快不少。html
咱們可使用程序員
<?php // a simple foreach() to traverse the SPL class names foreach(spl_classes() as $key=>$value) { echo $key.' -> '.$value.'<br />'; } ?>
來獲得全部可使用的標準的 SPL類庫:獲得結果以下:數據庫
Countable -> Countable
DirectoryIterator -> DirectoryIterator
DomainException -> DomainException
EmptyIterator -> EmptyIterator
FilesystemIterator -> FilesystemIterator
FilterIterator -> FilterIterator
GlobIterator -> GlobIterator
InfiniteIterator -> InfiniteIterator
InvalidArgumentException -> InvalidArgumentException
IteratorIterator -> IteratorIterator
LengthException -> LengthException
LimitIterator -> LimitIterator
LogicException -> LogicException
MultipleIterator -> MultipleIterator
NoRewindIterator -> NoRewindIterator
OuterIterator -> OuterIterator
OutOfBoundsException -> OutOfBoundsException
OutOfRangeException -> OutOfRangeException
OverflowException -> OverflowException
ParentIterator -> ParentIterator
RangeException -> RangeException
RecursiveArrayIterator -> RecursiveArrayIterator
RecursiveCachingIterator -> RecursiveCachingIterator
RecursiveCallbackFilterIterator -> RecursiveCallbackFilterIterator
RecursiveDirectoryIterator -> RecursiveDirectoryIterator
RecursiveFilterIterator -> RecursiveFilterIterator
RecursiveIterator -> RecursiveIterator
RecursiveIteratorIterator -> RecursiveIteratorIterator
RecursiveRegexIterator -> RecursiveRegexIterator
RecursiveTreeIterator -> RecursiveTreeIterator
RegexIterator -> RegexIterator
RuntimeException -> RuntimeException
SeekableIterator -> SeekableIterator
SplDoublyLinkedList -> SplDoublyLinkedList
SplFileInfo -> SplFileInfo
SplFileObject -> SplFileObject
SplFixedArray -> SplFixedArray
SplHeap -> SplHeap
SplMinHeap -> SplMinHeap
SplMaxHeap -> SplMaxHeap
SplObjectStorage -> SplObjectStorage
SplObserver -> SplObserver
SplPriorityQueue -> SplPriorityQueue
SplQueue -> SplQueue
SplStack -> SplStack
SplSubject -> SplSubject
SplTempFileObject -> SplTempFileObject
UnderflowException -> UnderflowException
UnexpectedValueException -> UnexpectedValueException
什麼是Iterators(迭代器)?設計模式
Iterator是專門用來遍歷特定的數據集的,例如數組,文件目錄結果,或者數據庫查詢出的結果集等等。這個描述其實不是十分的精確,具體信息後面會使用例子再講解。Iterator也分爲不少種,例如Array Iterator,Directory Iterator等等,咱們會先用DirectoryIterator 來了解它,可是在此以前有一點須要先明確,那就是不管哪一種的數據結構集 ,他們均可以經過標準的接口來訪問,也就是說訪問他們數據內容的方法都是一致的,這個但是PHP一個大大的進步哇~數組
將回調函數做用於Iterator上數據結構
由於Iterator是隻讀的,因此回調函數不能直接做用於其值上,可是這並不影響Iterator使用回調函數,下面的例子使用了一個簡單的數組來講明這一點:app
<?php function addCaps( Iterator $it ) { echo ucfirst( $it->current() ) . '<br />'; return true; } /*** an array of aussies ***/ $array = array( 'dingo', 'wombat', 'wallaby' ); try { $it = new ArrayIterator( $array ); iterator_apply( $it, 'addCaps', array($it) );//爲迭代器中每一個元素調用一個用戶自定義函數:iterator_apply( Traversable , callback [, array ] )$iterator$function$args
} catch(Exception $e) { /*** echo the error message ***/ echo $e->getMessage(); } ?>
上面的例子中須要注意的是方法addCaps必須返回true,iterator_apply函數纔會繼續向下遍歷執行,不然只會執行第一個元素就中止了。最終結果以下:框架
Dingo
Wombat
Wallaby
擴展DirectoryIterator:koa
<?php /*** class definition to extend Directory Iterator class ***/ class DirectoryReader extends DirectoryIterator { // constructor.. duh! function __construct($path) { /*** pass the $path off to the parent class constructor ***/ parent::__construct($path); } /*** return the current filename ***/ function current() { return parent::getFileName(); } /*** members are only valid if they are a directory ***/ function valid() { if(parent::valid()) { if (!parent::isDir()) { parent::next(); return $this->valid(); } return TRUE; } return FALSE; } } // end class try { /*** a new iterator object ***/ $it = new DirectoryReader('./'); /*** loop over the object if valid ***/ while($it->valid()) { /*** echo the current object member ***/ echo $it->current().'<br />'; /*** advance the internal pointer ***/ $it->next(); } } catch(Exception $e) { echo 'No files Found!<br />'; } ?>
上面的例子給咱們展現瞭如何重載Iterator裏的方法來減小代碼中的邏輯部分,這給重複的且靈活的使用類提供了很好了機會,所以減小了用戶代碼並加快了開發效率,另外使用Exception告訴咱們能夠很方便的捕獲錯誤而且處理它們。咱們還可使用isfile()方法來替代isDir()以只展現出文件,能夠作的事情是無窮盡的。
讓咱們來看看在上面的例子中咱們都作了些什麼。首先咱們建立了一個類繼承了內部的DirectoryIterator,在構造函數類咱們傳遞了 目錄$path,而後調用了父類中的構造函數,而且傳遞了$path.
$valid方法檢查了文件是否合法,這個是基於父類中的valid()方法,檢查當前Iterator是否有值,而後檢查當前Iterator是不是目錄,若是不是目錄就調用$parant::next() 檢查下一個值,咱們可使用filterIterator 來達到一樣的目的,可是這個後面再講。
ArrayObject
Arrayobject容許遍歷數組內部結構而且建立ArrayIterator的實例,像DirectoryIterator同樣,咱們能夠經過下面的代碼片斷看到ArrayObject的內部方法:
<?php foreach(get_class_methods(new ArrayObject()) as $key=>$method) { echo $key.' -> '.$method.'<br />'; } ?>
內部方法以下: 0 -> __construct 1 -> offsetExists 2 -> offsetGet 3 -> offsetSet 4 -> offsetUnset 5 -> append 6 -> getArrayCopy 7 -> count 8 -> getFlags 9 -> setFlags 10 -> asort 11 -> ksort 12 -> uasort 13 -> uksort 14 -> natsort 15 -> natcasesort 16 -> getIterator 17 -> exchangeArray 18 -> setIteratorClass 19 -> getIteratorClass
咱們將會經過多種方式來展示ArrayIterator,先來一個簡單點的:
<?php /*** a simple array ***/ $array = array('koala', 'kangaroo', 'wombat', 'wallaby', 'emu', 'kiwi', 'kookaburra', 'platypus'); /*** create the array object ***/ $arrayObj = new ArrayObject($array); /*** iterate over the array ***/ for($iterator = $arrayObj->getIterator(); $iterator->valid();$iterator->next()) { /*** output the key and current array value ***/ echo $iterator->key() . ' => ' . $iterator->current() . '<br />'; } ?>
上面的例子中咱們使用ArrayIterator遍歷了數組的內部結構,咱們也可使用foreach來遍歷上面的數組,那樣的話getInstance()方法就會被隱式的調用,key()和current()方法也屬於ArrayIterator 實例,從上面的代碼中咱們獲得了下面的結果:
0 => koala 1 => kangaroo 2 => wombat 3 => wallaby 4 => emu 5 => kiwi 6 => kookaburra 7 => platypus
通過了上面,咱們如今應該能夠去蕩蕩鞦韆了吧。爲了簡單起見,咱們仍是用上面的那個例子來講明如何添加或者刪除一個值經過iterator,值得注意的是ArrayObject::getIterator將會返回一個原始的Iterator實例給咱們。只有getIterator()方法是動態調用的