文档章节

Laravel5.2之PHP对象遍历(Iterator)

botkenni
 botkenni
发布于 2016/10/24 09:24
字数 1169
阅读 30
收藏 0

说明:本文章主要讲述PHP的对象遍历(Iterator)知识点。由于Laravel框架中就在集合(Collection)中用到了对象遍历知识点,故记录并学习之。同时,作者会将开发过程中的一些截图和代码黏上去,提高阅读效率。

Laravel中在基础集合类IlluminateSupportCollection、路由类中IlluminateRoutingRouteCollection和分页类中IlluminatePaginationPaginator等,都用到了对象遍历这个小知识点,这些类都是实现了IteratorAggregate这个接口,这个接口定义getIterator(),返回的是迭代器对象。PHP标准扩展库中提供了很多默认迭代器实现类,比较常用的是数组迭代器对象ArrayIterator,参考官网:迭代器

对象遍历(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;
}

输出的是:

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;
        }
    }

对象外部访问:

$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接口,同样可以遍历自定义的可不见属性,输出结果如下:

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对象。所以再重构下上面代码:

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源码并模仿之,也不错哦。

© 著作权归作者所有

共有 人打赏支持
botkenni
粉丝 20
博文 409
码字总数 434882
作品 0
西城
程序员
私信 提问
php的迭代器

PHP5开始支持了接口, 并且内置了Iterator接口, 所以如果你定义了一个类,并实现了Iterator接口,那么你的这个类对象就是ZENDITEROBJECT,否则就是ZENDITERPLAIN_OBJECT. 对于ZENDITERPLAIN...

stone_
2016/07/07
24
0
复习PHP-语言参考-预定义接口

1.Traversable 他是一个遍历接口规范 注意:发现一个有用的函数getdeclaredclasses,可以以数组形式显示当前脚本下所有已经定义的类名 2.Iterator Iterator迭代器继承自Traversable,是一种遍...

qzd1989
2014/05/03
0
0
ECMAScript Iterator和for...of循环

Iterator(遍历器)的概念 遍历器(Iterator)就是这样一种机制。它是一种接口,为各种不同的数据结构提供统一的访问机制。任何数据结构只要部署Iterator接口,就可以完成遍历操作(即依次处理...

墨马
2017/11/01
0
0
15、ES6的for...of遍历iterator对象

1、iterator接口。 如果一个对象部署了iterator接口那就能被for...of 遍历。并且for...of 只能遍历部署了iterator接口的对象。如下对象: 数组。 字符串。 arguments。 set容器。 map容器。 ...

王坤charlie
2018/03/18
0
0
设计模式-迭代器模式

模式定义 提供一种方法顺序访问一个聚合对象中的各种元素,而又不暴露该对象的内部表示。 模式结构 Iterator:迭代器接口。定义访问和遍历元素的接口。 ConcreteIterator:具体的迭代器实现对象...

wjk_snail
2016/08/18
11
0

没有更多内容

加载失败,请刷新页面

加载更多

树形结构的数据库表Schema设计

程序设计过程中,我们常常用树形结构来表征某些数据的关联关系,如企业上下级部门、栏目结构、商品分类等等,通常而言,这些树状结构需要借助于数据库完成持久化。然而目前的各种基于关系的数...

太菜鸟
18分钟前
0
0
Pod在多可用区worker节点上的高可用部署

一、 需求分析 当前kubernetes集群中的worker节点可以支持添加多可用区中的ECS,这种部署方式的目的是可以让一个应用的多个pod(至少两个)能够分布在不同的可用区,起码不能分布在同一个可用...

迷你芊宝宝
27分钟前
0
0
使用maven命令上传jar包到仓库

mvn deploy:deploy-file -DgroupId=com.jz.tss.service -DartifactId=tss-service -Dversion=1.9.02-SNAPSHOT -Dfile=E:/Workspace/tss-service/build/oracle/TSS-Service/WEB-INF/lib/TSS-S......

GodIsCj
28分钟前
1
0
mysql 向下无限递归(不使用函数,单纯sql)

表结构和数据 CREATE TABLE table1(id int, name varchar(10), parent_id int); INSERT table1 VALUES (1, 'Home', 0), (2, 'About', 1), (3, 'Contact', 1), (4, 'Legal', 2), ......

一雨成东
28分钟前
0
0
面试官问:ZooKeeper 一致性协议 ZAB 原理

一致性协议有很多种,比如 Paxos,Raft,2PC,3PC等等,今天我们讲一种协议,ZAB 协议,该协议应该是所有一致性协议中生产环境中应用最多的了。为什么呢?因为他是为 Zookeeper 设计的分布式...

Java爬坑之路
32分钟前
15
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部