PHP SPL 學習(一)

  • 話說真正作PHP程序員也將近三年了,感受仍是有老多東西不懂不瞭解,最近想學習ZF2 邊看框架邊想弄個博客出來,誰知道ZF框架裏面各類設計模式啊,各類高深的東西啊,各類不理解啊。最關鍵的是它無處不在的SPL的東西啊,雖然知道這東西好久了,但只是只知其一;不知其二,因此決定好好整理整理SPL 的知識。看看手冊 ,看看博客,決定整合翻譯翻譯前人的東西。
  • 原文:http://www.phpro.org/tutorials/Introduction-to-SPL.htm

主要內容:

什麼是SPL?php

  通俗點講SPL就是一套PHP 自帶的標準的類與接口的集合,使用它來處理一些平常事務 如遍歷文件目錄,遍歷數組,資源類型數據,效率上講會快不少。html

咱們可使用程序員

<?php
// a simple foreach() to traverse the SPL class names
foreach(spl_classes() as $key=>$value)
{
echo $key.' -&gt; '.$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()方法是動態調用的

相關文章
相關標籤/搜索