我一直在进行相当多的研究并得出结论我宁愿用愚蠢的旧scandir
和foreach
实现所有内容,而不是采用迭代器的方式
基本上,我需要一种获取目录内容的方法 - 可选择排序,可选地递归,并可选择按文件名过滤。哪个IMO是您对任何有些复杂的文件系统遍历所期望的最基本功能。
事实证明,RecursiveDirectoryIterator
和FilesystemIterator
都不支持排序或过滤。必须将它们包含在扩展ArrayObject
以实现排序的类中,或者FilterIterator
进行过滤。因此,为了实现这两个目标,你必须编写两个类,将所有内容包装在无数级别中,并且代码最终会看起来异乎寻常并且过于复杂。
我是否遗漏了一些关于这种方法的内容,还是应该抓住我的进度,用简单的愚蠢if/else/foreach
代码重写20多行中的所有内容?
答案 0 :(得分:6)
SPL中发现的迭代器并非都是“随时可用”的。它们是可用于创建任何所需内容的基本块。 FileSystemIterator
可能有一些基本的过滤功能,但你想自己创造更多,而且这很容易。
使用像FilesystemIterator
这样的迭代器的好处是,你可以从业务逻辑中将过滤逻辑从排序逻辑中分离出来。
说你有以下内容:
$dir = opendir('.');
while (($file = readdir($dir)) !== false) {
// business logic
}
以后,您决定只过滤MP3文件:
$dir = opendir('.');
while (($file = readdir($dir)) !== false) {
if (preg_match('|\.mp3$|i', $file)) {
// business logic
}
}
但是如何过滤MP3和JPG文件,或者小于5MB且只有一周的MP3文件,以及超过2MB的JPG文件,以及多个目录或递归目录等呢?你的“foreach / while”循环变成了一场噩梦,尽管它开始时非常好。
通过从业务逻辑中分离遍历逻辑,意味着它更易于维护,测试甚至重用:
$it = new DirectoryIterator("."); // Dir iterator
$it = new RegexIterator($it, "|\.mp3$|i"); // filter MP3's
$it = new FilesizeIterator($it, "<6MB"); // Only less than 6MB
$it = new LimitIterator($it, 0, 100); // First 100 items only
foreach ($it as $file) {
// extrabonus: $file is a SplFileInfo object
}
很容易想象我们如何将迭代器逻辑“构建”到更复杂的示例中,我们可以将RegexIterator
之类的东西重用于文件名以外的其他东西。它也更容易测试,因为我们只需要检查regexFilterIterator
是否正确过滤了正则表达式,就是这样。
排序等也可以根据您的喜好添加,但仍然是:您的业务逻辑没有变化,仍然与所有其他逻辑分离。
看看Symfony2的Finder
组件:它使用大量迭代器来过滤和排序项目。