zoukankan      html  css  js  c++  java
  • PHP SPL 学习(一)

    • 话说真正做PHP程序员也将近三年了,感觉还是有老多东西不懂不了解,最近想学习ZF2 边看框架边想弄个博客出来,谁知道ZF框架里面各种设计模式啊,各种高深的东西啊,各种不理解啊。最关键的是它无处不在的SPL的东西啊,虽然知道这东西很久了,但只是一知半解,所以决定好好整理整理SPL 的知识。看看手册 ,看看博客,决定整合翻译翻译前人的东西。
    • 原文:http://www.phpro.org/tutorials/Introduction-to-SPL.htm

    主要内容:

    什么是SPL?

      通俗点讲SPL就是一套PHP 自带的标准的类与接口的集合,使用它来处理一些日常事务 如遍历文件目录,遍历数组,资源类型数据,效率上讲会快很多。

    我们可以使用

    <?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使用回调函数,下面的例子使用了一个简单的数组来说明这一点:

    <?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 $iterator , callback $function [, array $args ] )
    
        }
        catch(Exception $e)
        {
            /*** echo the error message ***/
            echo $e->getMessage();
        }
    ?>

     上面的例子中需要注意的是方法addCaps必须返回true,iterator_apply函数才会继续向下遍历执行,否则只会执行第一个元素就停止了。最终结果如下:

    Dingo
    Wombat
    Wallaby

    扩展DirectoryIterator:

    <?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()方法是动态调用的

      

  • 相关阅读:
    csrf
    cookies和session区别
    关于Processing开发应用及发布分享的一些经验分享
    C++调用动态链接库DLL的隐式链接和显式链接基本方法小结
    C++最基本调用静态库的方法小结
    C++最基本调用动态链接库dll方法的小结
    基于Potplayer类播放器或Action!类录屏软件调取摄像头方式的定时抓拍保存图像方法小结
    基于Openframeworks调取摄像头方式的定时抓拍保存图像方法小结
    DOS使用技巧整理 [典型案例分享]
    正则表达式使用技巧整理
  • 原文地址:https://www.cnblogs.com/akulubala/p/3166599.html
Copyright © 2011-2022 走看看