Laravel學習筆記之PHP對象遍歷(Iterator)

說明:本文章主要講述PHP的對象遍歷(Iterator)知識點。因爲Laravel框架中就在集合(Collection)中用到了對象遍歷知識點,故記錄並學習之。同時,做者會將開發過程當中的一些截圖和代碼黏上去,提升閱讀效率。php

Laravel中在基礎集合類IlluminateSupportCollection、路由類中IlluminateRoutingRouteCollection和分頁類中IlluminatePaginationPaginator等,都用到了對象遍歷這個小知識點,這些類都是實現了IteratorAggregate這個接口,這個接口定義getIterator(),返回的是迭代器對象。PHP標準擴展庫中提供了不少默認迭代器實現類,比較經常使用的是數組迭代器對象ArrayIterator,參考官網:迭代器laravel

對象遍歷(Iterator)

基本遍歷

PHP5提供了遍歷對象屬性的方法,並且默認是可見屬性,如代碼中foreach遍歷對象屬性,默認的都是可見屬性:程序員

<?php
/**
 * Created by PhpStorm.
 * User: liuxiang
 * Date: 16/7/20
 * Time: 17:29
 */
class TestIterator {
    /**
     * @var string
     */
    public $name    = 'PHP';
    /**
     * @var string
     */
    public $address = 'php.net';

    /**
     * @var string
     */
    protected $sex  = 'man';

    /**
     * @var int
     */
    private $age    = 20;

}

$testIterator = new TestIterator();
foreach ($testIterator as $key => $value) {
    echo $key.':'.$value.PHP_EOL;
}

輸出的是:api

name:PHP
address:php.net

若是須要遍歷對象的不可見屬性,則在對象內部定義一個遍歷方法:數組

public function unAccessIterator()
    {
        echo 'Iterator the unaccess fields:'.PHP_EOL;
        foreach ($this as $key => $value) {
            echo $key.':'.$value.PHP_EOL;
        }
    }

對象外部訪問:composer

$testIterator->unAccessIterator();

將能夠遍歷對象的不可見屬性,輸出結果:框架

Iterator the unaccess fields:
name:PHP
address:php.net
sex:man
age:20

Iterator接口

PHP提供了Iterator接口,用來定義迭代器對象來自定義遍歷,因此利用Iterator接口來構造迭代器,須要實現Iterator定義的幾個方法:學習

<?php
/**
 * Created by PhpStorm.
 * User: liuxiang
 * Date: 16/7/20
 * Time: 17:29
 */
class TestIterator implements Iterator{
    /**
     * @var string
     */
    public $name    = 'PHP';
    /**
     * @var string
     */
    public $address = 'php.net';

    /**
     * @var string
     */
    protected $sex  = 'man';

    /**
     * @var int
     */
    private $age    = 20;

    /**
     * @var array
     */
    private $composerPackage;

    public function __construct($composerPackage = [])
    {
        $this->composerPackage = $composerPackage;
    }

    public function unAccessIterator()
    {
        echo 'Iterator the unaccess fields:'.PHP_EOL;
        foreach ($this as $key => $value) {
            echo $key.':'.$value.PHP_EOL;
        }
    }

    /**
     * Return the current element
     * @link http://php.net/manual/en/iterator.current.php
     * @return mixed Can return any type.
     * @since 5.0.0
     */
    public function current()
    {
        // TODO: Implement current() method.
        echo 'Return the current element:'.PHP_EOL;
        return current($this->composerPackage);
    }

    /**
     * Move forward to next element
     * @link http://php.net/manual/en/iterator.next.php
     * @return void Any returned value is ignored.
     * @since 5.0.0
     */
    public function next()
    {
        // TODO: Implement next() method.
        echo 'Move forward to next element:'.PHP_EOL;
        return next($this->composerPackage);
    }

    /**
     * Return the key of the current element
     * @link http://php.net/manual/en/iterator.key.php
     * @return mixed scalar on success, or null on failure.
     * @since 5.0.0
     */
    public function key()
    {
        // TODO: Implement key() method.
        echo 'Return the key of the current element:'.PHP_EOL;
        return key($this->composerPackage);
    }

    /**
     * Checks if current position is valid
     * @link http://php.net/manual/en/iterator.valid.php
     * @return boolean The return value will be casted to boolean and then evaluated.
     * Returns true on success or false on failure.
     * @since 5.0.0
     */
    public function valid()
    {
        // TODO: Implement valid() method.
        echo 'Checks if current position is valid:'.PHP_EOL;
        return current($this->composerPackage) !== false;
    }

    /**
     * Rewind the Iterator to the first element
     * @link http://php.net/manual/en/iterator.rewind.php
     * @return void Any returned value is ignored.
     * @since 5.0.0
     */
    public function rewind()
    {
        // TODO: Implement rewind() method.
        echo 'Rewind the Iterator to the first element:'.PHP_EOL;
        reset($this->composerPackage);
    }
}

/*
$testIterator = new TestIterator();
foreach ($testIterator as $key => $value) {
    echo $key.':'.$value.PHP_EOL;
}
$testIterator->unAccessIterator();*/

$testIterator = new TestIterator([
    'symfony/http-foundation',
    'symfony/http-kernel',
    'guzzle/guzzle',
    'monolog/monolog'
]);
foreach ($testIterator as $key => $value) {
    echo $key.':'.$value.PHP_EOL;
}

成員變量$composerPackage是不可見的,經過實現Iterator接口,一樣能夠遍歷自定義的可不見屬性,輸出結果以下:this

Rewind the Iterator to the first element:
Checks if current position is valid:
Return the current element:
Return the key of the current element:
0:symfony/http-foundation
Move forward to next element:
Checks if current position is valid:
Return the current element:
Return the key of the current element:
1:symfony/http-kernel
Move forward to next element:
Checks if current position is valid:
Return the current element:
Return the key of the current element:
2:guzzle/guzzle
Move forward to next element:
Checks if current position is valid:
Return the current element:
Return the key of the current element:
3:monolog/monolog
Move forward to next element:
Checks if current position is valid:

IteratorAggregate接口

PHP真心爲程序員考慮了不少,實現IteratorAggragate接口後只需實現getIterator()方法直接返回迭代器對象,就不須要實現Iterator接口須要的一些方法來建立一些迭代器對象,由於PHP已經提供了不少迭代器對象如ArrayIterator對象。因此再重構下上面代碼:lua

class TestCollection implements IteratorAggregate{
    ...
    /**
     * @var array
     */
    private $composerPackage;
    
    ...
    
    /**
     * Retrieve an external iterator
     * @link http://php.net/manual/en/iteratoraggregate.getiterator.php
     * @return Traversable An instance of an object implementing <b>Iterator</b> or
     * <b>Traversable</b>
     * @since 5.0.0
     */
    public function getIterator()
    {
        // TODO: Implement getIterator() method.
        return new ArrayIterator($this->composerPackage);
    }
   
}

$testCollection = new TestCollection([
    'symfony/http-foundation',
    'symfony/http-kernel',
    'guzzle/guzzle',
    'monolog/monolog'
]);
foreach ($testCollection as $key => $value) {
    echo $key.':'.$value.PHP_EOL;
}

一樣的,能遍歷$testCollection對象的不可見屬性$composerPackage,輸出結果:

0:symfony/http-foundation
1:symfony/http-kernel
2:guzzle/guzzle
3:monolog/monolog

文章開頭聊到Laravel中就用到了IteratorAggragate這個接口,能夠看看文件的源碼。

總結:PHP提供的對象遍歷特性功能仍是頗有用處的,下一篇準備看下generator生成器知識點,generator提供了另一種方式定義Iterator。多多使用Laravel,研究Laravel源碼並模仿之,也不錯哦。

歡迎關注Laravel-China
RightCapital招聘Laravel DevOps

相關文章
相關標籤/搜索