Php-SPL庫中的迭代器類詳解

SPL提供了多個迭代器類,分別提供了迭代訪問、過濾數據、緩存結果、控制分頁等功能。,因爲php總是在不斷壯大,我儘可能列出SPL中所有的迭代類。下面其中一些迭代器類是需要php5.4,另外一些如SearhIteratoer類在最新的php版本中已經去除

1.ArrayIteratoer

PHP數組創建一個迭代器,當其和IteratorAggregate類一起使用時,免去了直接實現Iterator接口的方法的工作。

<示例>

$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

返回給定數量的結果以及從集合中取出結果的起始索引點:

<示例>

// 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()函數來合併數組。

$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 ($iterator as $current) {
    echo $current."\n";
}
/**output
a
b
c
d
e
f
 */


4. FilterIterator

基於OuterIterator接口,用於過濾數據,返回符合條件的元素。必須實現一個抽象方法accept(),此方法必須爲迭代器的當前項返回truefalse

class UserFilter extends FilterIterator
{
    private $userFilter;

    public function __construct(Iterator $iterator, $filter)
    {
        parent::__construct($iterator);
        $this->userFilter = $filter;
    }

    public function 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 ($iterator as $result) {
    echo $result['name'];
}

/**output
Jonathan
**/


5. RegexIterator

繼承FilterIterator,支持使用正則表達式模式匹配和修改迭代器中的元素。經常用於將字符串匹配。

$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

用來執行提前讀取一個元素的迭代操作,例如可以用於確定當前元素是否爲最後一個元素。

$array = array('koala', 'kangaroo', 'wombat', 'wallaby', 'emu', 'kiwi', 'kookaburra', 'platypus');
try {
    $object = new CachingIterator(new ArrayIterator($array));
    foreach ($object as $value) {
        echo $value;
        if ($object->hasNext()) {
            echo ',';
        }
    }
}
catch (Exception $e) {
    echo $e->getMessage();
}
/**output
koala,kangaroo,wombat,wallaby,emu,kiwi,kookaburra,platypus
 **/

8. SeekableIterator

用於創建非順序訪問的迭代器,允許跳轉到迭代器中的任何一點上。

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

9. NoRewindIterator

用於不能多次迭代的集合,適用於在迭代過程中執行一次性操作。

$fruit = array('apple', 'banana', 'cranberry');
$arr = new ArrayObject($fruit);
$it = new NoRewindIterator($arr->getIterator());
echo "Fruit A:\n";
foreach ($it as $item) {
    echo $item . "\n";
}

echo "Fruit B:\n";
foreach ($it as $item) {
    echo $item . "\n";
}
/**output
Fruit A:
apple
banana
cranberry
Fruit B:
 **/


10. EmptyIterator

一種佔位符形式的迭代器,不執行任何操作。當要實現某個抽象類的方法並且這個方法需要返回一個迭代器時,可以使用這種迭代器。

11. InfiniteIterator

用於持續地訪問數據,當迭代到最後一個元素時,會再次從第一個元素開始迭代訪問。

$arrayit = new ArrayIterator(array('cat', 'dog'));
$infinite = new InfiniteIterator($arrayit);
$limit = new LimitIterator($infinite, 0, 7);
foreach ($limit as $value) {
    echo "$value\n";
}
/**output
cat
dog
cat
dog
cat
dog
cat
 **/

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

將一個樹形結構的迭代器展開爲一維結構。

$fruits = array("a" => "lemon", "b" => "orange", array("a" => "apple", "p" => "pear"));
$arrayiter = new RecursiveArrayIterator($fruits);
$iteriter = new RecursiveIteratorIterator($arrayiter);
foreach ($iteriter as $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

以可視在方式顯示一個樹形結構。

$hey = array("a" => "lemon", "b" => "orange", array("a" => "apple", "p" => "pear"));
$awesome = new RecursiveTreeIterator(
    new RecursiveArrayIterator($hey),
    null, null, RecursiveIteratorIterator::LEAVES_ONLY
);
foreach ($awesome as $line)
    echo $line . PHP_EOL;

/**output
|-lemon
|-orange
    |-apple
    \-pear
 **/



15. ParentIterator

是一個擴展的FilterIterator迭代器,它可以過濾掉來自於RecursiveIterator迭代器的非父元素,只找出子節點的鍵值。通俗來說,就是去枝留葉。

$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()方法訪問當前正在迭代的迭代器。

class TestsOnlyFilter extends RecursiveFilterIterator
{
    public function 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迭代器作爲迭代對象。

$rArrayIterator = new RecursiveArrayIterator(array('葉1', array('tet3', '葉4', '葉5')));
$rRegexIterator = new RecursiveRegexIterator($rArrayIterator, '/^葉/',
    RecursiveRegexIterator::ALL_MATCHES);

foreach ($rRegexIterator as $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)

同時執行過濾和回調操作,在找到一個匹配的元素之後會調用回調函數。

$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

檢查目錄中是否包含更多項


$it = new DirectoryIterator("../");
foreach ($it as $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

檢查當前位置是否合法


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

22. FilesystemIterator

DirectoryIterator的遍歷器

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

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

用於迭代器的連接器,具體看示例

$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 ($mit as $person) {
    print_r($person);
}
/**output
Array
(
    [ID] => 001
    [NAME] => 張三
    [AGE] => 22
)
Array
(
    [ID] => 002
    [NAME] => 李四
    [AGE] => 23
)
Array
(
    [ID] => 003
    [NAME] => 王五
    [AGE] => 11
)
 **/

25. RecursiveCallbackFilterIterator(PHP5.4)

RecursiveIterator迭代器上進行遞歸操作,同時執行過濾和回調操作,在找到一個匹配的元素之後會調用回調函數。

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;
// 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
        )

)
 **/

********************************************

* 作者:葉文濤 

* 標題:Php-SPL庫中的迭代器類詳解

* 參考:

*  php手冊http://php.net/manual/en/spl.iterators.php

*《PHP高級程序設計:模式、框架和測試》 Kevin McArthur 著 汪泳 等譯

******************轉載請註明來源 ***************



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章