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(),此方法必须为迭代器的当前项返回true或false
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 **/