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

      

  • 相关阅读:
    JZOJ 3034. 【NOIP2012模拟10.17】独立集
    JZOJ 3035. 【NOIP2012模拟10.17】铁轨
    JZOJ 1259. 牛棚安排
    数位DP JZOJ 3316. 非回文数字
    JZOJ 3046. 游戏
    JZOJ 3013. 填充棋盘
    debian 安装oracle提供的java8
    java 汉字转拼音 PinYin4j
    debian ssh设置root权限登陆 Permission denied, please try again
    java并发下订单生成策略
  • 原文地址:https://www.cnblogs.com/akulubala/p/3166599.html
Copyright © 2020-2023  润新知