zoukankan      html  css  js  c++  java
  • PHP SPL他们留下的宝石

    Rafael Dohms 上面的篇文章 让我为之惊艳。忍不住就翻译了下来。同一时候补充了部分内容。

    SPL,PHP 标准库(Standard PHP Library) ,此从 PHP 5.0 起内置的组件和接口。而且从 PHP5.3 已逐渐的成熟。SPL 事实上在全部的 PHP5 开发环境中被内置。同一时候无需不论什么设置。

    似乎众多的 PHP 开发者基本没有使用它,甚至闻所未闻。究其原因。能够追述到它那阳春白雪般的说明文档,使你忽略了「它的存在」。SPL 这块宝石宛如铁达尼的「海洋之心」般,被沉入海底。而如今它应该被我们捞起,并将它穿戴在应有的位置 。而这也是这篇文章所要表述的观点。

    那么,SPL 提供了什么?

    SPL 对 PHP 引擎进行了扩展。比如 ArrayAccess、Countable 和 SeekableIterator 等接口,它们用于以数组形式操作对象。同一时候,你还能够使用 RecursiveIterator、ArrayObejcts 等其它迭代器进行数据的迭代操作。

    它还内置几个的对象比如 Exceptions、SplObserver、Spltorage 以及 splautoloadregister、splclasses、iteratorapply 等的帮助函数(helper functions)。用于重载相应的功能。

    这些工具聚合在一起就好比是把多功能的瑞士军刀,善用它们能够从质上提升 PHP 的代码效率。那么。我们怎样发挥它的威力?

    重载 autoloader

    假设你是位「教科书式的程序猿」,那么你保证了解怎样使用 __autoload 去取代 includes/requires 操作惰性加载相应的类,对不?

    但久之,你会发现你已经陷入了困境,首先是你要保证你的类文件必须在指定的文件路径中,比如在 Zend 框架中你必须使用「_」来切割类、方法名称(你怎样解决这一问题?)。

    另外的一个问题,就是当项目变得越来越复杂, __autoload 内的逻辑也会变得对应的复杂。到最后,甚至你会增加异常推断。以及将全部的加载类的逻辑如数写到当中。

    大家都知道「鸡蛋不能放到一个篮子中」。利用 SPL 能够分离 __autoload 的加载逻辑。

    仅仅须要写个你自己的 autoload 函数。然后利用 SPL 提供的函数重载它。

    比如上述 Zend 框架的问题。你能够重载 Zend loader 相应的方法,假设它没有找到相应的类,那么就使用你先前定义的函数。

    <?php
    class MyLoader {
        public static function doAutoload($class) {
            // 本模块相应的 autoload 操作
        }
    }
    
    spl_autoload_register( array('MyLoader', 'doAutoload') );
    ?>

    正如你所见, spl autoload register 还能以数组的形式增加多个加载逻辑。

    同一时候,你还能够利用spl autoload unregister 移除已经不再须要的加载逻辑。这功能总会用到的。

    迭代器

    迭代是常见设计模式之中的一个,普遍应用于一组数据中的统一的遍历操作。能够毫不夸张的说,SPL 提供了全部你须要的相应数据类型的迭代器。

    有个很好的案例就是遍历文件夹。常规的做法就是使用 scandir 。然后跳过「.「 和 「..」,以及其他未满足条件的文件。

    比如你须要遍历个某个文件夹抽取当中的图片文件,就须要推断是否是 jpg、gif 结尾。

    以下的代码就是使用 SPL 的迭代器运行上述递归寻找指定文件夹中的图片文件的样例:

    <?php
    class RecursiveFileFilterIterator extends FilterIterator {
        // 满足条件的扩展名
        protected $ext = array('jpg','gif');
    
        /**
         * 提供 $path 并生成相应的文件夹迭代器
         */
        public function __construct($path) {
            parent::__construct(new RecursiveIteratorIterator(new RecursiveDirectoryIterator($path)));
        }
    
        /**
         * 检查文件扩展名是否满足条件
         */
        public function accept() {
            $item = $this->getInnerIterator();
            if ($item->isFile() && 
                    in_array(pathinfo($item->getFilename(), PATHINFO_EXTENSION), $this->ext)) {
                return TRUE;
            }
        }
    }
    
    // 实例化
    foreach (new RecursiveFileFilterIterator('/path/to/something') as $item) {
        echo $item . PHP_EOL;
    }
    ?

    >


    你可能会说。这不是花了很多其它的代码去办同一件事情吗?那么。查看上面的代码,你不是拥有了具有高度重用并且能够測试的代码了吗 :)

    以下是 SPL 提供的其它的迭代器:

    • RecursiveIterator
    • RecursiveIteratorIterator
    • OuterIterator
    • IteratorIterator
    • FilterIterator
    • RecursiveFilterIterator
    • ParentIterator
    • SeekableIterator
    • LimitIterator
    • GlobIterator
    • CachingIterator
    • RecursiveCachingIterator
    • NoRewindIterator
    • AppendIterator
    • RecursiveIteratorIterator
    • InfiniteIterator
    • RegexIterator
    • RecursiveRegexIterator
    • EmptyIterator
    • RecursiveTreeIterator
    • ArrayIterator

    自 PHP5.3 開始。会内置其它很多其它的迭代器。我想你都能够尝试下。也许它能改变你编写传统代码的习惯。

    SplFixedArray

    SPL 还内置了一系列的数组操作工具。比如能够使用 SplFixedArray 实例化一个固定长度的数组。那么为什么要使用它?由于它更快,甚至它关系着你的工资问题 :)

    我们知道 PHP 常规的数组包括不同类型的键,比如数字、字符串等,而且长度是可变的。正是由于这些「高级功能」。PHP 以散列(hash)的方式通过键得到相应的值 -- 事实上这在特定情况这会造成性能问题。

    而 SplFixedArray 由于是使用固定的数字键,所以它并没有使用散列存储方式。

    不确切的说,甚至你能够觉得它就是个 C 数组。这就是为什么 SplFixedArray 会比通常数组要快的原因(仅在 PHP5.3 中)。

    那究竟有多快呢。以下的组数据能够让你窥其究竟。


    假设你须要大量的数组操作。那么你能够尝试下,相信它是值得信赖的。

    数据结构

    同一时候 SPL 还提供了些数据结构基本类型的实现 。尽管我们能够使用传统的变量类型来描写叙述数据结构,比如用数组来描写叙述堆栈(Strack)-- 然后使用相应的方式 pop 和 push(arraypop()、arraypush()),但你得时刻小心,·由于毕竟它们不是专门用于描写叙述数据结构的 -- 一次误操作就有可能破坏该堆栈。

    而 SPL 的 SplStack 对象则严格以堆栈的形式描写叙述数据,并提供相应的方法。

    同一时候。这种代码应该也能理解它在操作堆栈而非某个数组,从而能让你的同伴更好的理解相应的代码。而且它更快。

    最后,可能上述那些慘白的样例还不足矣「诱惑你」去使用 SPL。实践出真知,SPL 很多其它、更强大的功能须要你自己去挖掘。而它由于宝石般缓缓掉漆。散发着灿烂的能力。

    版权声明:本文博客原创文章。博客,未经同意,不得转载。

  • 相关阅读:
    HDU 2639 Bone Collector II (01背包,第k解)
    POJ 2184 Cow Exhibition 奶牛展(01背包,变形)
    hihoCoder #1165 : 益智游戏 (挑战赛11 B题)
    UVA 562 Dividing coins 分硬币(01背包,简单变形)
    POJ Charm Bracelet 挑饰品 (常规01背包)
    hiho一下 第四十四周 博弈游戏·Nim游戏(直接公式解)
    UVA 624 CD(01背包,要记录路径)
    118 Pascal's Triangle 帕斯卡三角形 杨辉三角形
    117 Populating Next Right Pointers in Each Node II 每个节点的右向指针 II
    116 Populating Next Right Pointers in Each Node 每个节点的右向指针
  • 原文地址:https://www.cnblogs.com/yxwkf/p/4642785.html
Copyright © 2011-2022 走看看