PHP中for和foreach背后发生了什么

在循环结构中,for是很常用的一种表达式,在学习python迭代器的时候,感觉很有意思,就反过来看看PHP中for和foreach是如何处理的

for和foreach简单描述

php中的for处理方式类似于c语言,只要expr2表达式为真,则循环会一直继续下去:

for (expr1; expr2; expr3)
    statement

php中的foreach主要是为了遍历数组和对象:
foreach开始执行的时候,数组内部的指针会自动指向第一个单元,每进行一次循环,数组和对象的内部指针为自动移动一位,尽量在移动的时候不要修改其值.

foreach (array_expression as $value)
    statement
foreach (array_expression as $key => $value)
    statement

迭代器

上述的forforeach描述很简单.

foreach能够循环任何迭代器对象,而这些对象不仅仅是数组,可以是任何类型的对象.
一个迭代器是一个对象,迭代器对象可能是一个数组,也可能是一个目录,甚至可以是数据库查询结果集.

SPL(the Standard PHP Library)通过内建的类,提供了很大数量的迭代器,从而让代码更有效,更可读.

The DirectoryIterator class

try {
    $iterator = new \DirectoryIterator($directory);
    foreach ($iterator as $info) {
        if (!$info->isDot() && $info->isFile()) {
            echo $info->__toString() . "\n";
        }
    }
} catch (Exception $e) {
    echo get_class($e) . ": " . $e->getMessage();
}

ArrayIterator

$arr = ["java", "python", "php"];
$iter = new ArrayIterator($arr);
foreach ($iter as $key => $value) {
    echo $key . ":  " . $value . "\n";
}

看一个另类的用法:

$val = ["shell", "python", "php"];
$arr = new \ArrayIterator($val);
while ($arr->valid()) {
    echo $arr->key() . " : " . $arr->current() . ":" . $arr->offsetGet($arr->key()) . PHP_EOL;
    $arr->offsetSet($arr->key(), "ok");
    $arr->next();
}
print_r($arr->getArrayCopy());

next()方法就是进行指针移动的关键

为什么使用迭代器

  • 在处理具有大量数据的对象时,使用迭代器比数组更有效,因为在foreach迭代数组的时候会拷贝数组对象,而SPL迭代器通过内部封装每一次只会输出一个元素则更有效.
  • 延迟加载,迭代器在使用的时候能够加载仅仅需要的数据
  • 迭代器真正有用点在于用途比较广泛,能够通过实现迭代器接口创造出更多的数据结构

如何创建一个自定义迭代器

SPL迭代器类已经提供了很多功能的迭代器,PHP也提供了接口Iterator,IteratorAggregate让程序员创建自定义的迭代器类.

只要实现接口Iterator的五个方法就可以创建一个迭代器类,rewind(),current(), key(),next(),valid()

当迭代开始,PHP调用rewind()方法让指针回到数据集开始处,通过调用valid()方法检查数据是否可用,假如返回为true,则调用current()方法获取当前指针对应的值,同时key()能够获取到当前指针的key,最后再调用next()方法重复上述的流程.

class myIterator implements Iterator {
}

IteratorAggregate
Iterator接口比较适合于创建一个内部的迭代器,理想的情况下,使用IteratorAggregate更加适合创建一个外部的迭代器,只要实现getIterator()方法即可.

IteratorAggregateIterator的关系类似于容器和具体容器的关系

class myIteratorAggregate implements IteratorAggregate {

    protected $arr = array("php", "python", "shell");
    protected $type;

    function __construct($type = 1) {
        $this->type = $type;
    }

    public function getIterator() {
        if ($this->type == 1)
            return new ArrayIterator($this->arr);
        else
            return new myIterator($this->arr);
    }
}
$obj = new myIteratorAggregate ;
foreach ($obj as $v) {
    echo $v . "\n";
}

总结:

  • 理解迭代器很容易,但是创建一个有意义的迭代器则不容易,这就类似于学习算法可能很容易,但如何实际运用则是另外一回事.
  • 通过SPL迭代器,避免了程序员自造轮子,同时也提供了更多的数据结构.
  • 至于使用数组还是迭代器,则要根据实际情况,比如从效率,可读性等方面衡量.
  • 通过SPL类和接口,PHP提供了更多扩展,这也是PHP越来越现代化的证明.
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,529评论 5 475
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,015评论 2 379
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,409评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,385评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,387评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,466评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,880评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,528评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,727评论 1 295
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,528评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,602评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,302评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,873评论 3 306
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,890评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,132评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,777评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,310评论 2 342

推荐阅读更多精彩内容

  • PHP 学习目录 ├─PHP视频教程 1 LAMP网站构建 │ ├─PHP教程 1.1.1 新版视频形式介绍│ ...
    曹渊说创业阅读 16,143评论 29 417
  • 一 预定义接口 1.1 遍历 Traversable(遍历)接口 检测一个类是否可以被foreach遍历,该接口不...
    coderhu阅读 1,196评论 0 0
  • 听先生和几个堂弟堂妹聊小时候的事。几个人都说最喜欢也最感谢奶奶。 堂弟说:“奶奶那么爱干净,却总是允许我们把家里弄...
    羽宙儿阅读 383评论 0 0
  • 京城秋凉落叶花,只剩黄绿冷天涯。 山中还有红枫美,昙花一现为晚霞。
    老槐树阅读 133评论 0 3
  • 当代中国经济高速发展,生活节奏不断加快,我们在忙于追求高品质生活的同时,却忽略了自己的健康。调查发现,健康人群仅占...
    夕颜李阅读 462评论 0 0