我正在尝试在 PHP 5 中有效地使用迭代器,但由于网络上没有很多像样的示例,事实证明这有点困难。
我正在尝试遍历一个目录,并读取其中的所有 (php) 文件以搜索已定义的类。然后我想要做的是返回一个关联数组,其中类名作为键,文件路径作为值。
通过使用 RecursiveDirectoryIterator(),我可以递归遍历目录。 通过将其传递给 RecursiveIteratorIterator,我可以将目录的内容检索为一维迭代器。 然后对此使用过滤器,我可以过滤掉所有目录和非 php 文件,这些文件只会留下我想要考虑的文件。
我现在想要做的是能够将这个迭代器传递给另一个迭代器(不确定哪个合适),这样当它遍历每个条目时,它可以检索一个数组,它需要组合成一个 master数组。
解释起来有点复杂,所以这里有一个代码示例:
// $php_files now represents an array of SplFileInfo objects representing files under $dir that match our criteria
$php_files = new PhpFileFilter(new RecursiveIteratorIterator(new RecursiveDirectoryIterator($dir)));
class ClassDetector extends FilterIterator {
public function accept() {
$file = $this->current(); // get the current item, which will be an SplFileInfo object
// Match all the classes contained within this file
if (preg_match($regex, $file->getContents(), $match)) {
// Return an assoc array of all the classes matched, the class name as key and the filepath as value
return array(
'class1' => $file->getFilename(),
'class2' => $file->getFilename(),
'class3' => $file->getFilename(),
);
}
}
}
foreach (new ClassDetector($php_files) as $class => $file) {
print "{$class} => {$file}\n";
}
// Expected output:
// class1 => /foo.php
// class2 => /foo.php
// class3 => /foo.php
// class4 => /bar.php
// class5 => /bar.php
// ... etc ...
正如您从这个示例中看到的,我有点劫持 FilterIterator 的 accept() 方法,我知道这是完全不正确的用法 - 但我仅将其用作示例来演示我如何只想要一个函数被调用,并返回一个合并到主数组中的数组。
目前我在想我将不得不使用其中一个 RecursionIterators,因为这似乎是他们所做的,但我不喜欢使用两种不同方法的想法 (hasChildren()和 getChildren()) 来实现目标。
简而言之,我试图确定我可以使用(或扩展)哪个 Iterator 来让它传递对象的一维数组(?),并让它将结果数组组合成一个主数组并返回。
我意识到还有其他几种解决方法,比如:
$master = array();
foreach($php_files as $file) {
if (preg_match($regex, $file->getContents(), $match)) {
// create $match_results
$master = array_merge($master, $match_results);
}
}
但这违背了使用迭代器的目的,而且作为解决方案也不是很优雅。
无论如何,我希望我已经解释得够清楚了。感谢您阅读到这里,并提前回答您的问题 :)
最佳答案
是的,我最终设法解决了这个问题。我必须使用递归迭代器,因为输入迭代器本质上是生成子结果,并且我扩展了 IteratorIterator,它已经具有循环迭代器的功能。
无论如何,这是一个代码示例,以防万一这对其他人有帮助。这假设您已经传入了一个 SplFileInfo 对象数组(无论如何它们都是 DirectoryIterator 的结果)。
class
ClassMatcher
extends
IteratorIterator
implements
RecursiveIterator
{
protected $matches;
public function hasChildren() {
return preg_match_all(
'#class (\w+)\b#ism',
file_get_contents($this->current()->getPathname()),
$this->matches
);
}
public function getChildren() {
$classes = $this->matches[1];
return new RecursiveArrayIterator(
array_combine(
$classes, // class name as key
array_fill(0, count($classes), $this->current()->getPathname()) // file path as value
)
);
}
}
关于php - 从另一个迭代器的结果创建新的迭代器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/575106/