在遍历文件系统时使用SPL迭代器有什么好处?

时间:2015-01-29 08:46:52

标签: php spl

我一直在进行相当多的研究并得出结论我宁愿用愚蠢的旧scandirforeach实现所有内容,而不是采用迭代器的方式

基本上,我需要一种获取目录内容的方法 - 可选择排序,可选地递归,并可选择按文件名过滤。哪个IMO是您对任何有些复杂的文件系统遍历所期望的最基本功能。

事实证明,RecursiveDirectoryIteratorFilesystemIterator都不支持排序过滤。必须将它们包含在扩展ArrayObject以实现排序的类中,或者FilterIterator进行过滤。因此,为了实现这两个目标,你必须编写两个类,将所有内容包装在无数级别中,并且代码最终会看起来异乎寻常并且过于复杂。

我是否遗漏了一些关于这种方法的内容,还是应该抓住我的进度,用简单的愚蠢if/else/foreach代码重写20多行中的所有内容?

1 个答案:

答案 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组件:它使用大量迭代器来过滤和排序项目。