SPL提供了多个迭代器类,分别提供了迭代访问、过滤数据、缓存结果、控制分页等功能。,因为php总是在不断壮大,我尽可能列出SPL中所有的迭代类。下面其中一些迭代器类是需要php5.4,另外一些如SearhIteratoer类在最新的php版本中已经去除
1.ArrayIteratoer
从PHP数组创建一个迭代器,当其和IteratorAggregate类一起使用时,免去了直接实现Iterator接口的方法的工作。
<示例>
1
2
3
4
5
6
7
8
9
10
11
12
13
|
$b
=
array
(
'name'
=>
'mengzhi'
,
'age'
=>
'12'
,
'city'
=>
'shanghai'
);
$a
=
new
ArrayIterator(
$b
);
$a
->append(
array
(
'home'
=>
'china'
,
'work'
=>
'developer'
));
$c
=
$a
->getArrayCopy();
print_r(
$a
);
print_r(
$c
);
|
/**output
ArrayIterator Object
(
[storage:ArrayIterator:private] => Array
(
[name] => mengzhi
[age] => 12
[city] => shanghai
[0] => Array
(
[home] => china
[work] => developer
)
)
)
Array
(
[name] => mengzhi
[age] => 12
[city] => shanghai
[0] => Array
(
[home] => china
[work] => developer
)
)
**/
2. LimitIterator
返回给定数量的结果以及从集合中取出结果的起始索引点:
<示例>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
// Create an iterator to be limited
$fruits
=
new
ArrayIterator(
array
(
'apple'
,
'banana'
,
'cherry'
,
'damson'
,
'elderberry'
));
// Loop over first three fruits only
foreach
(
new
LimitIterator(
$fruits
, 0, 3)
as
$fruit
) {
var_dump(
$fruit
);
}
echo
"\n"
;
// Loop from third fruit until the end
// Note: offset starts from zero for apple
foreach
(
new
LimitIterator(
$fruits
, 2)
as
$fruit
) {
print_r(
$fruit
);
}
|
/**output
string(5) "apple"
string(6) "banana"
string(6) "cherry"
cherrydamsonelderberry
*/
3. AppendIterator
按顺序迭代访问几个不同的迭代器。例如,希望在一次循环中迭代访问两个或者更多的组合。这个迭代器的append方法类似于array_merge()函数来合并数组。
1
2
3
4
5
6
7
8
|
$array_a
=
new
ArrayIterator(
array
(
'a'
,
'b'
,
'c'
));
$array_b
=
new
ArrayIterator(
array
(
'd'
,
'e'
,
'f'
));
$iterator
=
new
AppendIterator;
$iterator
->append(
$array_a
);
$iterator
->append(
$array_b
);
foreach
(
$iteratoras
$current
) {
echo
$current
.
"\n"
;
}
|
/**output
a
b
c
d
e
f
*/
4. FilterIterator
基于OuterIterator接口,用于过滤数据,返回符合条件的元素。必须实现一个抽象方法accept(),此方法必须为迭代器的当前项返回true或false
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
|
class
UserFilter
extends
FilterIterator
{
private
$userFilter
;
publicfunction __construct(Iterator
$iterator
,
$filter
)
{
parent::__construct(
$iterator
);
$this
->userFilter =
$filter
;
}
publicfunction accept()
{
$user
=
$this
->getInnerIterator()->current();
if
(
strcasecmp
(
$user
[
'name'
],
$this
->userFilter) == 0) {
return
false;
}
return
true;
}
}
$array
=
array
(
array
(
'name'
=>
'Jonathan'
,
'id'
=>
'5'
),
array
(
'name'
=>
'Abdul'
,
'id'
=>
'22'
)
);
$object
=
new
ArrayObject(
$array
);
//去除掉名为abdul的人员
$iterator
=
new
UserFilter(
$object
->getIterator(),
'abdul'
);
foreach
(
$iteratoras
$result
) {
echo
$result
[
'name'
];
}
/**output
Jonathan
**/
|
5. RegexIterator
继承FilterIterator,支持使用正则表达式模式匹配和修改迭代器中的元素。经常用于将字符串匹配。
1
2
3
4
|
$a
=
new
ArrayIterator(
array
(
'test1'
,
'test2'
,
'test3'
));
$i
=
new
RegexIterator(
$a
,
'/^(test)(\d+)/'
, RegexIterator::REPLACE);
$i
->replacement =
'$2:$1'
;
print_r(iterator_to_array(
$i
));
|
/**output
Array
(
[0] => 1:test
[1] => 2:test
[2] => 3:test
)
**/
6. IteratorIterator
一种通用类型的迭代器,所有实现了Traversable接口的类都可以被它迭代访问。
7. CachingIterator
用来执行提前读取一个元素的迭代操作,例如可以用于确定当前元素是否为最后一个元素。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
$array
=
array
(
'koala'
,
'kangaroo'
,
'wombat'
,
'wallaby'
,
'emu'
,
'kiwi'
,
'kookaburra'
,
'platypus'
);
try
{
$object
=
new
CachingIterator(
new
ArrayIterator(
$array
));
foreach
(
$objectas
$value
) {
echo
$value
;
if
(
$object
->hasNext()) {
echo
','
;
}
}
}
catch
(Exception
$e
) {
echo
$e
->getMessage();
}
/**output
koala,kangaroo,wombat,wallaby,emu,kiwi,kookaburra,platypus
**/
|
8. SeekableIterator
用于创建非顺序访问的迭代器,允许跳转到迭代器中的任何一点上。
1
2
3
4
|
$array
=
array
(
"apple"
,
"banana"
,
"cherry"
,
"damson"
,
"elderberry"
);
$iterator
=
new
ArrayIterator(
$array
);
$iterator
->seek(3);
echo
$iterator
->current();
|
/**output
damson
**/
9. NoRewindIterator
用于不能多次迭代的集合,适用于在迭代过程中执行一次性操作。
1
2
3
4
5
6
7
8
9
10
11
12
|
$fruit
=
array
(
'apple'
,
'banana'
,
'cranberry'
);
$arr
=
new
ArrayObject(
$fruit
);
$it
=
new
NoRewindIterator(
$arr
->getIterator());
echo
"Fruit A:\n"
;
foreach
(
$itas
$item
) {
echo
$item
.
"\n"
;
}
echo
"Fruit B:\n"
;
foreach
(
$itas
$item
) {
echo
$item
.
"\n"
;
}
|
/**output
Fruit A:
apple
banana
cranberry
Fruit B:
**/
10. EmptyIterator
一种占位符形式的迭代器,不执行任何操作。当要实现某个抽象类的方法并且这个方法需要返回一个迭代器时,可以使用这种迭代器。
11. InfiniteIterator
用于持续地访问数据,当迭代到最后一个元素时,会再次从第一个元素开始迭代访问。
1
2
3
4
5
6
7
|
$arrayit
=
new
ArrayIterator(
array
(
'cat'
,
'dog'
));
$infinite
=
new
InfiniteIterator(
$arrayit
);
$limit
=
new
LimitIterator(
$infinite
, 0, 7);
foreach
(
$limitas
$value
) {
echo
"$value\n"
;
}
/**output
|
cat
dog
cat
dog
cat
dog
cat
**/
12. RecursiveArrayIterator
创建一个用于递归形式数组结构的迭代器,类似于多维数组.它为许多更复杂的迭代器提供了所需的操作,如RecursiveTreeIterator和RecursiveIteratorIterator迭代器。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
$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
2
3
4
5
6
7
|
$fruits
=
array
(
"a"
=>
"lemon"
,
"b"
=>
"orange"
,
array
(
"a"
=>
"apple"
,
"p"
=>
"pear"
));
$arrayiter
=
new
RecursiveArrayIterator(
$fruits
);
$iteriter
=
new
RecursiveIteratorIterator(
$arrayiter
);
foreach
(
$iteriteras
$key
=>
$value
) {
$d
=
$iteriter
->getDepth();
echo
"depth=$d k=$key v=$value\n"
;
}
|
/**output
depth=0 k=a v=lemon
depth=0 k=b v=orange
depth=1 k=a v=apple
depth=1 k=p v=pear
**/
14. RecursiveTreeIterator
以可视在方式显示一个树形结构。
1
2
3
4
5
6
7
|
$hey
=
array
(
"a"
=>
"lemon"
,
"b"
=>
"orange"
,
array
(
"a"
=>
"apple"
,
"p"
=>
"pear"
));
$awesome
=
new
RecursiveTreeIterator(
new
RecursiveArrayIterator(
$hey
),
null, null, RecursiveIteratorIterator::LEAVES_ONLY
);
foreach
(
$awesomeas
$line
)
echo
$line
. PHP_EOL;
|
/**output
|-lemon
|-orange
|-apple
\-pear
**/
15. ParentIterator
是一个扩展的FilterIterator迭代器,它可以过滤掉来自于RecursiveIterator迭代器的非父元素,只找出子节点的键值。通俗来说,就是去枝留叶。
1
2
3
4
|
$hey
=
array
(
"a"
=>
"lemon"
,
"b"
=>
"orange"
,
array
(
"a"
=>
"apple"
,
"p"
=>
"pear"
));
$arrayIterator
=
new
RecursiveArrayIterator(
$hey
);
$it
=
new
ParentIterator(
$arrayIterator
);
print_r(iterator_to_array(
$it
));
|
/**output
Array
(
[0] => Array
(
[a] => apple
[p] => pear
)
)
**/
16. RecursiveFilterIterator
是FilterIterator迭代器的递归形式,也要求实现抽象的accept()方法,但在这个方法中应该使用$this->getInnerIterator()方法访问当前正在迭代的迭代器。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
class
TestsOnlyFilter
extends
RecursiveFilterIterator
{
publicfunction accept()
{
// 找出含有“叶”的元素
return
$this
->hasChildren() || (mb_strpos(
$this
->current(),
"叶"
) !== FALSE);
}
}
$array
=
array
(
"叶1"
,
array
(
"李2"
,
"叶3"
,
"叶4"
),
"叶5"
);
$iterator
=
new
RecursiveArrayIterator(
$array
);
$filter
=
new
TestsOnlyFilter(
$iterator
);
$filter
=
new
RecursiveIteratorIterator(
$filter
);
print_r(iterator_to_array(
$filter
));
|
/**output
Array
(
[0] => 叶1
[1] => 叶3
[2] => 叶5
)
**/
17. RecursiveRegexIterator
是RegexIterator迭代器的递归形式,只接受RecursiveIterator迭代器作为迭代对象。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
$rArrayIterator
=
new
RecursiveArrayIterator(
array
(
'叶1'
,
array
(
'tet3'
,
'叶4'
,
'叶5'
)));
$rRegexIterator
=
new
RecursiveRegexIterator(
$rArrayIterator
,
'/^叶/'
,
RecursiveRegexIterator::ALL_MATCHES);
foreach
(
$rRegexIteratoras
$key1
=>
$value1
) {
if
(
$rRegexIterator
->hasChildren()) {
// print all children
echo
"Children: "
;
foreach
(
$rRegexIterator
->getChildren()
as
$key
=>
$value
) {
echo
$value
.
" "
;
}
echo
"\n"
;
}
else
{
echo
"No children\n"
;
}
}
|
/**output
No children
Children: 叶4 叶5
**/
18. RecursiveCachingIterator
在RecursiveIterator迭代器上执行提前读取一个元素的递归操作。
19. CallbackFilterIterator(PHP5.4)
同时执行过滤和回调操作,在找到一个匹配的元素之后会调用回调函数。
1
2
3
4
5
6
7
8
9
|
$hey
=
array
(
"李1"
,
"叶2"
,
"叶3"
,
"叶4"
,
"叶5"
,
"叶6"
,);
$arrayIterator
=
new
RecursiveArrayIterator(
$hey
);
function
isYe(
$current
)
{
return
mb_strpos(
$current
,
'叶'
) !== false;
}
$rs
=
new
CallbackFilterIterator(
$arrayIterator
,
'isYe'
);
print_r(iterator_to_array(
$rs
));
|
/**output
Array
(
[0] => 叶2
[1] => 叶3
[2] => 叶4
[3] => 叶5
[4] => 叶6
)
**/
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
2
3
4
5
6
7
|
$it
=
new
DirectoryIterator(
"../"
);
foreach
(
$itas
$file
) {
//用isDot ()方法分别过滤掉“.”和“..”目录
if
(!
$it
->isDot()) {
echo
$file
.
"\n"
;
}
}
|
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
3
4
5
6
|
$path
=
realpath
(
'../'
);
$objects
=
new
RecursiveIteratorIterator(
new
RecursiveDirectoryIterator(
$path
), RecursiveIteratorIterator::SELF_FIRST);
foreach
(
$objectsas
$name
=>
$object
) {
echo
"$name\n"
;
}
22. Filesyste
|
mIterator
是DirectoryIterator的遍历器
1
2
3
4
|
$it
=
new
FilesystemIterator(
'../'
);
foreach
(
$itas
$fileinfo
) {
echo
$fileinfo
->getFilename() .
"\n"
;
}
|
23. GlobIterator
带匹配模式的文件遍历器
//找出../目录中.php扩展名的文件
1
2
3
4
5
6
7
8
9
10
11
|
$iterator
=
new
GlobIterator(
'./*.php'
);
if
(!
$iterator
->
count
()) {
echo
'无php文件'
;
}
else
{
$n
= 0;
printf(
"总计 %d 个php文件\r\n"
,
$iterator
->
count
());
foreach
(
$iteratoras
$item
) {
printf(
"[%d] %s\r\n"
, ++
$n
,
$iterator
->key());
}
}
/**outpu
|
t
总计 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
2
3
4
5
6
7
8
9
10
11
12
|
$person_id
=
new
ArrayIterator(
array
(
'001'
,
'002'
,
'003'
));
$person_name
=
new
ArrayIterator(
array
(
'张三'
,
'李四'
,
'王五'
));
$person_age
=
new
ArrayIterator(
array
(22, 23, 11));
$mit
=
new
MultipleIterator(MultipleIterator::MIT_KEYS_ASSOC);
$mit
->attachIterator(
$person_id
,
"ID"
);
$mit
->attachIterator(
$person_name
,
"NAME"
);
$mit
->attachIterator(
$person_age
,
"AGE"
);
echo
"连接的迭代器个数:"
.
$mit
->countIterators() .
"\n"
;
//3
foreach
(
$mitas
$person
) {
print_r(
$person
);
}
/**outp
|
ut
Array
(
[ID] => 001
[NAME] => 张三
[AGE] => 22
)
Array
(
[ID] => 002
[NAME] => 李四
[AGE] => 23
)
Array
(
[ID] => 003
[NAME] => 王五
[AGE] => 11
)
**/
25. RecursiveCallbackFilterIterator(PHP5.4)
在RecursiveIterator迭代器上进行递归操作,同时执行过滤和回调操作,在找到一个匹配的元素之后会调用回调函数。
1
2
3
4
5
6
7
8
9
10
11
|
function
doesntStartWithLetterT(
$current
)
{
$rs
=
$current
->getFileName();
return
$rs
[0] !==
'T'
;
}
$rdi
=
new
RecursiveDirectoryIterator(__DIR__);
$files
=
new
RecursiveCallbackFilterIterator(
$rdi
,
'doesntStartWithLetterT'
);
foreach
(
new
RecursiveIteratorIterator(
$files
)
as
$file
) {
echo
$file
->getPathname() . PHP_EOL;
}
|
26. SimpleXMLIterator
XMl文档访问迭代器,可实现访问xml中所有节点
$xml = <<<XML
<books>
<book>
<title>PHP Basics</title>
<author>Jim Smith</author>
</book>
<book>XML basics</book>
</books>
XML;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
// SimpleXML转换为数组
function
sxiToArray(
$sxi
)
{
$a
=
array
();
for
(
$sxi
->
rewind
();
$sxi
->valid();
$sxi
->next()) {
if
(!
array_key_exists
(
$sxi
->key(),
$a
)) {
$a
[
$sxi
->key()] =
array
();
}
if
(
$sxi
->hasChildren()) {
$a
[
$sxi
->key()][] = sxiToArray(
$sxi
->current());
}
else
{
$a
[
$sxi
->key()][] =
strval
(
$sxi
->current());
}
}
return
$a
;
}
|
$xmlIterator = new SimpleXMLIterator($xml);
$rs = sxiToArray($xmlIterator);
print_r($rs);
/**output
Array
(
[book] => Array
(
[0] => Array
(
[title] => Array
(
[0] => PHP Basics
)
[author] => Array
(
[0] => Jim Smith
)
)
[1] => XML basics
)
)
**/