如何从DirectoryIterator解释这种行为?

时间:2014-05-02 18:15:25

标签: php

任何人都能解释为什么会这样吗?附带问题:有没有办法让它使用DirectoryIterator工作,所以正确的对象存储在$j$k

<?php

// my name is dirtest.php and I live on my own in a directory

$i = new DirectoryIterator(".");
$j = [];
$k = [];

function println($val) {
    echo $val . "\n";
}

println('First time:');
foreach ($i as $x) {
    $j[] = $x;
    println($x->getFilename());
}
println('Second time:');
foreach ($j as $y) {
    $k[] = $y->getFilename();
    println($y->getFilename());
}

预期:

First time:
.
..
dirtest.php

Second time:
.
..
dirtest.php

实际:

First time:
.
..
dirtest.php

Second time:

第一次通过所有似乎都符合预期,但是,在$j中存储对每个文件的引用后,每个元素似乎都会丢失其引用。 (我开始尝试使用this library中的过滤器/地图功能,但将问题缩小到上面的列表。)

使用PHP 5.4.27进行测试。

2 个答案:

答案 0 :(得分:2)

$xDirectoryIterator类型的对象引用,因此$j中的所有元素都相同。迭代器完成工作后,无法显示任何内容。

http://www.php.net/manual/en/language.oop5.object-comparison.php

当您定义对象的值时,不会复制该对象,但会对该对象的引用进行归因,因此它们是相同的。

现在,当DirectoryIteratorforeach()中进行迭代时,每次迭代都会调用next()方法,因此每次$x都是相同的引用,但是对象已经改变。但是所有引用仍然指向同一个对象,最后,在迭代结束后,它不会引用任何文件。

为了好玩,你可以做:

for($i=1;$i<count($j);$i++) {
    var_dump($j[$i-1]===$j[$i]); echo "\n";
}

你应该获得所有行bool(true)

答案 1 :(得分:0)

我真正想要做的就是这样:

<?php
use Functional as F;

$i = new DirectoryIterator('.');

$j = F\filter($i, function ($x) { return $x->isDot(); });

看起来不错,但$j不是你想象的那样!

但我可以增加额外的一步......

<?php
use Functional as F;

$i = new DirectoryIterator('.');

function deref($xs) {
    return F\map($i, function ($x) { return clone $x; });
}

$j = F\filter(
    deref($i),
    function ($x) { return $x->isDot(); })
);

$j现在是一个很酷的过滤后的 beer 数组,其中包含我的目录条目。