Php-SPL库中的迭代器类详解(转)

SPL提供了多个迭代器类,分别提供了迭代访问、过滤数据、缓存结果、控制分页等功能。,因为php总是在不断壮大,我尽可能列出SPL中所有的迭代类。下面其中一些迭代器类是需要php5.4,另外一些如SearhIteratoer类在最新的php版本中已经去除

1.ArrayIteratoer

PHP数组创建一个迭代器,当其和IteratorAggregate类一起使用时,免去了直接实现Iterator接口的方法的工作。

<示例>

 

 1 $b = array(
 2     'name'=> 'mengzhi',
 3     'age' => '12',
 4     'city'=> 'shanghai'
 5 );
 6 $a = new ArrayIterator($b);
 7 $a->append(array(
 8                 'home' => 'china',
 9                 'work' => 'developer'
10            ));
11 $c = $a->getArrayCopy();
12 print_r($a);
13 print_r($c);
14 
15 /**output
16 ArrayIterator Object
17 (
18     [storage:ArrayIterator:private] => Array
19     (
20     [name] => mengzhi
21             [age] => 12
22             [city] => shanghai
23             [0] => Array
24     (
25     [home] => china
26                     [work] => developer
27                 )
28 
29         )
30 
31 )
32 Array
33     (
34     [name] => mengzhi
35     [age] => 12
36     [city] => shanghai
37     [0] => Array
38     (
39     [home] => china
40             [work] => developer
41         )
42 
43 )
44 **/

 

2. LimitIterator

返回给定数量的结果以及从集合中取出结果的起始索引点:

<示例>

 1 // Create an iterator to be limited
 2 $fruits = new ArrayIterator(array(
 3                                  'apple',
 4                                  'banana',
 5                                  'cherry',
 6                                  'damson',
 7                                  'elderberry'
 8                             ));
 9 // Loop over first three fruits only
10 foreach (new LimitIterator($fruits, 0, 3) as $fruit) {
11     var_dump($fruit);
12 }
13 echo "\n";
14 // Loop from third fruit until the end
15 // Note: offset starts from zero for apple
16 foreach (new LimitIterator($fruits, 2) as $fruit) {
17     print_r($fruit);
18 }
19 
20 /**output
21 string(5) "apple"
22 string(6) "banana"
23 string(6) "cherry"
24 
25 cherrydamsonelderberry
26  */

3. AppendIterator

  按顺序迭代访问几个不同的迭代器。例如,希望在一次循环中迭代访问两个或者更多的组合。这个迭代器的append方法类似于array_merge()函数来合并数组。

 

 1 $array_a = new ArrayIterator(array('a', 'b', 'c'));
 2 $array_b = new ArrayIterator(array('d', 'e', 'f'));
 3 $iterator = new AppendIterator;
 4 $iterator->append($array_a);
 5 $iterator->append($array_b);
 6 foreach ($iterator as $current) {
 7     echo $current."\n";
 8 }
 9 /**output
10 a
11 b
12 c
13 d
14 e
15 f
16  */

 

4. FilterIterator

基于OuterIterator接口,用于过滤数据,返回符合条件的元素。必须实现一个抽象方法accept(),此方法必须为迭代器的当前项返回truefalse

 

 1 class UserFilter extends FilterIterator
 2 {
 3     private $userFilter;
 4 
 5     public function __construct(Iterator $iterator, $filter)
 6     {
 7         parent::__construct($iterator);
 8         $this->userFilter = $filter;
 9     }
10 
11     public function accept()
12     {
13         $user = $this->getInnerIterator()->current();
14         if (strcasecmp($user['name'], $this->userFilter) == 0) {
15             return false;
16         }
17         return true;
18     }
19 }
20 
21 $array = array(
22     array(
23         'name' => 'Jonathan',
24         'id'   => '5'
25     ),
26     array(
27         'name' => 'Abdul',
28         'id'   => '22'
29     )
30 );
31 $object = new ArrayObject($array);
32 //去除掉名为abdul的人员
33 $iterator = new UserFilter($object->getIterator(), 'abdul');
34 foreach ($iterator as $result) {
35     echo $result['name'];
36 }
37 
38 /**output
39 Jonathan
40 **/

 

5. RegexIterator

继承FilterIterator,支持使用正则表达式模式匹配和修改迭代器中的元素。经常用于将字符串匹配。

 

 1 $a = new ArrayIterator(array('test1', 'test2', 'test3'));
 2 $i = new RegexIterator($a, '/^(test)(\d+)/', RegexIterator::REPLACE);
 3 $i->replacement = '$2:$1';
 4 print_r(iterator_to_array($i));
 5 
 6 /**output
 7 Array
 8 (
 9     [0] => 1:test
10     [1] => 2:test
11     [2] => 3:test
12 )
13  **/

 

6. IteratorIterator

一种通用类型的迭代器,所有实现了Traversable接口的类都可以被它迭代访问。

7. CachingIterator

用来执行提前读取一个元素的迭代操作,例如可以用于确定当前元素是否为最后一个元素。

 

 1 $array = array('koala', 'kangaroo', 'wombat', 'wallaby', 'emu', 'kiwi', 'kookaburra', 'platypus');
 2 try {
 3     $object = new CachingIterator(new ArrayIterator($array));
 4     foreach ($object as $value) {
 5         echo $value;
 6         if ($object->hasNext()) {
 7             echo ',';
 8         }
 9     }
10 }
11 catch (Exception $e) {
12     echo $e->getMessage();
13 }
14 /**output
15 koala,kangaroo,wombat,wallaby,emu,kiwi,kookaburra,platypus
16  **/

 

8. SeekableIterator

用于创建非顺序访问的迭代器,允许跳转到迭代器中的任何一点上。

 

1 $array = array("apple", "banana", "cherry", "damson", "elderberry");
2 $iterator = new ArrayIterator($array);
3 $iterator->seek(3);
4 echo $iterator->current();
5 /**output
6 damson
7  **/

 

9. NoRewindIterator

用于不能多次迭代的集合,适用于在迭代过程中执行一次性操作。

 

 1 $fruit = array('apple', 'banana', 'cranberry');
 2 $arr = new ArrayObject($fruit);
 3 $it = new NoRewindIterator($arr->getIterator());
 4 echo "Fruit A:\n";
 5 foreach ($it as $item) {
 6     echo $item . "\n";
 7 }
 8 
 9 echo "Fruit B:\n";
10 foreach ($it as $item) {
11     echo $item . "\n";
12 }
13 /**output
14 Fruit A:
15 apple
16 banana
17 cranberry
18 Fruit B:
19  **/

 

10. EmptyIterator

一种占位符形式的迭代器,不执行任何操作。当要实现某个抽象类的方法并且这个方法需要返回一个迭代器时,可以使用这种迭代器。

11. InfiniteIterator

用于持续地访问数据,当迭代到最后一个元素时,会再次从第一个元素开始迭代访问。

 

 1 $arrayit = new ArrayIterator(array('cat', 'dog'));
 2 $infinite = new InfiniteIterator($arrayit);
 3 $limit = new LimitIterator($infinite, 0, 7);
 4 foreach ($limit as $value) {
 5     echo "$value\n";
 6 }
 7 /**output
 8 cat
 9 dog
10 cat
11 dog
12 cat
13 dog
14 cat
15  **/

 

12. RecursiveArrayIterator

创建一个用于递归形式数组结构的迭代器,类似于多维数组.它为许多更复杂的迭代器提供了所需的操作,如RecursiveTreeIterator和RecursiveIteratorIterator迭代器。

$fruits = array("a" => "lemon", "b" => "orange", array("a" => "apple", "p" => "pear"));
$iterator = new RecursiveArrayIterator($fruits);
while ($iterator->valid()) {
    //检查是否含有子节点
    if ($iterator->hasChildren()) {
        //输出所以字节点
        foreach ($iterator->getChildren() as $key => $value) {
            echo $key . ' : ' . $value . "\n";
        }
    } else {
        echo "No children.\n";
    }
    $iterator->next();
}

/**output
No children.
No children.
a : apple
p : pear
 **/

13. RecursiveIteratorIterator

将一个树形结构的迭代器展开为一维结构。

 1 $fruits = array("a" => "lemon", "b" => "orange", array("a" => "apple", "p" => "pear"));
 2 $arrayiter = new RecursiveArrayIterator($fruits);
 3 $iteriter = new RecursiveIteratorIterator($arrayiter);
 4 foreach ($iteriter as $key => $value) {
 5     $d = $iteriter->getDepth();
 6     echo "depth=$d k=$key v=$value\n";
 7 }
 8 
 9 /**output
10 depth=0 k=a v=lemon
11 depth=0 k=b v=orange
12 depth=1 k=a v=apple
13 depth=1 k=p v=pear
14  **/

14. RecursiveTreeIterator

以可视在方式显示一个树形结构。

 

 1 $hey = array("a" => "lemon", "b" => "orange", array("a" => "apple", "p" => "pear"));
 2 $awesome = new RecursiveTreeIterator(
 3     new RecursiveArrayIterator($hey),
 4     null, null, RecursiveIteratorIterator::LEAVES_ONLY
 5 );
 6 foreach ($awesome as $line)
 7     echo $line . PHP_EOL;
 8 
 9 /**output
10 |-lemon
11 |-orange
12     |-apple
13     \-pear
14  **/

 

15. ParentIterator

是一个扩展的FilterIterator迭代器,它可以过滤掉来自于RecursiveIterator迭代器的非父元素,只找出子节点的键值。通俗来说,就是去枝留叶。

 

 1 $hey = array("a" => "lemon", "b" => "orange", array("a" => "apple", "p" => "pear"));
 2 $arrayIterator = new RecursiveArrayIterator($hey);
 3 $it = new ParentIterator($arrayIterator);
 4 print_r(iterator_to_array($it));
 5 /**output
 6 Array
 7     (
 8     [0] => Array
 9     (
10         [a] => apple
11         [p] => pear
12     )
13 )
14  **/

 

16. RecursiveFilterIterator

FilterIterator迭代器的递归形式,也要求实现抽象的accept()方法,但在这个方法中应该使用$this->getInnerIterator()方法访问当前正在迭代的迭代器。

 1 class TestsOnlyFilter extends RecursiveFilterIterator
 2 {
 3     public function accept()
 4     {
 5         // 找出含有“叶”的元素
 6         return $this->hasChildren() || (mb_strpos($this->current(), "叶") !== FALSE);
 7     }
 8 }
 9 
10 $array = array("叶1", array("李2", "叶3", "叶4"), "叶5");
11 $iterator = new RecursiveArrayIterator($array);
12 $filter = new TestsOnlyFilter($iterator);
13 $filter = new RecursiveIteratorIterator($filter);
14 print_r(iterator_to_array($filter));
15 /**output
16 Array
17 (
18     [0] => 叶1
19     [1] => 叶3
20     [2] => 叶5
21 )
22 **/

17. RecursiveRegexIterator

RegexIterator迭代器的递归形式,只接受RecursiveIterator迭代器作为迭代对象。

 1 $rArrayIterator = new RecursiveArrayIterator(array('叶1', array('tet3', '叶4', '叶5')));
 2 $rRegexIterator = new RecursiveRegexIterator($rArrayIterator, '/^叶/',
 3     RecursiveRegexIterator::ALL_MATCHES);
 4 
 5 foreach ($rRegexIterator as $key1 => $value1) {
 6     if ($rRegexIterator->hasChildren()) {
 7         // print all children
 8         echo "Children: ";
 9         foreach ($rRegexIterator->getChildren() as $key => $value) {
10             echo $value . " ";
11         }
12         echo "\n";
13     } else {
14         echo "No children\n";
15     }
16 }
17 /**output
18 No children
19 Children: 叶4 叶5 
20  **/

18. RecursiveCachingIterator

在RecursiveIterator迭代器上执行提前读取一个元素的递归操作。


19. CallbackFilterIterator(PHP5.4)

同时执行过滤和回调操作,在找到一个匹配的元素之后会调用回调函数。

 

 1 $hey = array( "李1", "叶2", "叶3", "叶4", "叶5", "叶6",);
 2 $arrayIterator = new RecursiveArrayIterator($hey);
 3 function isYe($current)
 4 {
 5     return mb_strpos($current,'叶') !== false;
 6 }
 7 
 8 $rs = new CallbackFilterIterator($arrayIterator, 'isYe');
 9 print_r(iterator_to_array($rs));
10 
11 /**output
12 Array
13 (
14     [0] => 叶2
15     [1] => 叶3
16     [2] => 叶4
17     [3] => 叶5
18     [4] => 叶6
19 )
20  **/

 

20. DirectoryIterator

目录文件遍历器

 

方    法

描    述

DirectoryIterator::getSize

得到文件大小

DirectoryIterator::getType

得到文件类型

DirectoryIterator::isDir

如果当前项是一个目录,返回true

DirectoryIterator::isDot

如果当前项是...,返回true

DirectoryIterator::isExecutable

如果文件可执行,返回true

DirectoryIterator::isFile

如果文件是一个常规文件,返回true

DirectoryIterator::isLink

如果文件是一个符号链接,返回true

DirectoryIterator::isReadable

如果文件可读,返回true

DirectoryIterator::isWritable

如果文件可写,返回true

DirectoryIterator::key

返回当前目录项

DirectoryIterator::next

移动到下一项

DirectoryIterator::rewind

将目录指针返回到开始位置

DirectoryIterator::valid

检查目录中是否包含更多项

 

1 $it = new DirectoryIterator("../");
2 foreach ($it as $file) {
3     //用isDot ()方法分别过滤掉“.”和“..”目录
4     if (!$it->isDot()) {
5         echo $file . "\n";
6     }
7 }

21. RecursiveDirectoryIterator

递归目录文件遍历器,可实现列出所有目录层次结构,而不是只操作一个目录。

 

方    法

描    述

RecursiveDirectoryIterator::getChildren

如果这是一个目录,为当前项返回一个迭代器

RecursiveDirectoryIterator::hasChildren

返回当前项是否是一个目录而不是...

RecursiveDirectoryIterator::key

返回当前目录项的路径和文件名

RecursiveDirectoryIterator::next

移动到下一项

RecursiveDirectoryIterator::rewind

将目录指针返回到开始位置

RecursiveIteratorIterator::current

访问当前元素值

RecursiveIteratorIterator::getDepth

得到递归迭代的当前深度

RecursiveIteratorIterator::getSubIterator

得到当前活动子迭代器

RecursiveIteratorIterator::key

访问当前键

RecursiveIteratorIterator::next

前移到下一个元素

RecursiveIteratorIterator::rewind

将迭代器返回到顶级内层迭代器的第一个元素

RecursiveIteratorIterator::valid

检查当前位置是否合法

1 //列出指定目录中所有文件
2 $path = realpath('../');
3 $objects = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($path), RecursiveIteratorIterator::SELF_FIRST);
4 foreach ($objects as $name => $object) {
5     echo "$name\n";
6 }

22. FilesystemIterator

DirectoryIterator的遍历器

1 $it = new FilesystemIterator('../');
2 foreach ($it as $fileinfo) {
3     echo $fileinfo->getFilename() . "\n";
4 }

23. GlobIterator

带匹配模式的文件遍历器

//找出../目录中.php扩展名的文件
$iterator = new GlobIterator('./*.php');
if (!$iterator->count()) {
    echo '无php文件';
} else {
    $n = 0;
    printf("总计 %d 个php文件\r\n", $iterator->count());
    foreach ($iterator as $item) {
        printf("[%d] %s\r\n", ++$n, $iterator->key());
    }
}
/**output
总计 23 个php文件
[1] .\1.php
[2] .\11.php
[3] .\12.php
[4] .\13.php
[5] .\14.php
[6] .\15.php
[7] .\16.php
[8] .\17.php
[9] .\19.php
[10] .\2.php
[11] .\20.php
[12] .\21.php
[13] .\22.php
[14] .\23.php
[15] .\24.php
[16] .\25.php
[17] .\26.php
[18] .\3.php
[19] .\4.php
[20] .\5.php
[21] .\7.php
[22] .\8.php
[23] .\9.php
 **/

24. MultipleIterator

用于迭代器的连接器,具体看示例

 1 $person_id = new ArrayIterator(array('001', '002', '003'));
 2 $person_name = new ArrayIterator(array('张三', '李四', '王五'));
 3 $person_age = new ArrayIterator(array(22, 23, 11));
 4 $mit = new MultipleIterator(MultipleIterator::MIT_KEYS_ASSOC);
 5 $mit->attachIterator($person_id, "ID");
 6 $mit->attachIterator($person_name, "NAME");
 7 $mit->attachIterator($person_age, "AGE");
 8 echo "连接的迭代器个数:".$mit->countIterators() . "\n"; //3
 9 foreach ($mit as $person) {
10     print_r($person);
11 }
12 /**output
13 Array
14 (
15     [ID] => 001
16     [NAME] => 张三
17     [AGE] => 22
18 )
19 Array
20 (
21     [ID] => 002
22     [NAME] => 李四
23     [AGE] => 23
24 )
25 Array
26 (
27     [ID] => 003
28     [NAME] => 王五
29     [AGE] => 11
30 )
31  **/

25. RecursiveCallbackFilterIterator(PHP5.4)

RecursiveIterator迭代器上进行递归操作,同时执行过滤和回调操作,在找到一个匹配的元素之后会调用回调函数。

 1 function doesntStartWithLetterT($current)
 2 {
 3     $rs = $current->getFileName();
 4     return $rs[0] !== 'T';
 5 }
 6 
 7 $rdi = new RecursiveDirectoryIterator(__DIR__);
 8 $files = new RecursiveCallbackFilterIterator($rdi, 'doesntStartWithLetterT');
 9 foreach (new RecursiveIteratorIterator($files) as $file) {
10     echo $file->getPathname() . PHP_EOL;
11 }

26. SimpleXMLIterator

XMl文档访问迭代器,可实现访问xml中所有节点

 

 1 $xml = <<<XML
 2 <books>
 3     <book>
 4         <title>PHP Basics</title>
 5         <author>Jim Smith</author>
 6     </book>
 7     <book>XML basics</book>
 8 </books>
 9 XML;
10 // SimpleXML转换为数组
11 function sxiToArray($sxi)
12 {
13     $a = array();
14     for ($sxi->rewind(); $sxi->valid(); $sxi->next()) {
15         if (!array_key_exists($sxi->key(), $a)) {
16             $a[$sxi->key()] = array();
17         }
18         if ($sxi->hasChildren()) {
19             $a[$sxi->key()][] = sxiToArray($sxi->current());
20         } else {
21             $a[$sxi->key()][] = strval($sxi->current());
22         }
23     }
24     return $a;
25 }
26 
27 $xmlIterator = new SimpleXMLIterator($xml);
28 $rs = sxiToArray($xmlIterator);
29 print_r($rs);
30 /**output
31 Array
32 (
33     [book] => Array
34         (
35             [0] => Array
36                 (
37                     [title] => Array
38                         (
39                             [0] => PHP Basics
40                         )
41 
42                     [author] => Array
43                         (
44                             [0] => Jim Smith
45                         )
46 
47                 )
48 
49             [1] => XML basics
50         )
51 
52 )
53  **/

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

posted @ 2014-03-05 19:43  幻星宇  阅读(681)  评论(0编辑  收藏  举报