我想玩一些PHP的迭代器,并设法得到一个可靠的(从我的理解)构建。我的目标是在父文件夹内迭代并获得2个节点;在此过程中构建分层树阵列。显然,我可以使用glob和几个嵌套循环相当容易地做到这一点,但我想使用Spl类来实现这一点。
所有这一切,我已经玩SplHeap和SplObjectStore到层次结构并失败了。什么弄乱我的面条是我正常的递归方法失败(内存不足错误)和我的成功落在一个循环方法循环每个节点,添加到一个数组。问题是它忽略了setMaxDepth()方法并遍历所有子节点。我考虑过设置一个$ var ++来增加循环,限制节点,但我不相信这是“正确的方法”。
Anywho,代码(对不起任何孤立的代码,如果有的话 - 只是忽略它)......
<?php
namespace Tree;
use RecursiveFilterIterator,
RecursiveDirectoryIterator,
RecursiveIteratorIterator;
class Filter extends RecursiveFilterIterator {
public static $FILTERS = array(
'.git', '.gitattributes', '.gitignore', 'index.php'
);
public function accept() {
if (!$this->isDot() && !in_array($this->current()->getFilename(), self::$FILTERS))
return TRUE;
return FALSE;
}
}
class DirTree {
const MAX_DEPTH = 2;
private static $iterator;
private static $objectStore;
public function __construct() {
error_reporting(8191);
$path = realpath('./');
try {
$dirItr = new RecursiveDirectoryIterator($path);
$filterItr = new Filter($dirItr);
$objects = new RecursiveIteratorIterator($filterItr, RecursiveIteratorIterator::SELF_FIRST);
$objects->setMaxDepth(self::MAX_DEPTH);
echo '<pre>';
print_r($this->build_hierarchy($objects));
} catch(Exception $e) {
die($e->getMessage());
}
}
public function build_hierarchy($iterator){
$array = array();
foreach ($iterator as $fileinfo) {
if ($fileinfo->isDir()) {
// Directories and files have labels
$current = array(
'label' => $fileinfo->getFilename()
);
// Only directories have children
if ($fileinfo->isDir()) {
$current['children'] = $this->build_hierarchy($iterator->getChildren());
}
// Append the current item to this level
$array[] = $current;
}
}
return $array;
}
}
$d = new DirTree;
答案 0 :(得分:1)
RecursiveIteratorIterator
主要用于为您提供一个迭代器,其行为类似于平面列表上的迭代器,但平面列表实际上只是递归遍历中的一个序列。它通过内部管理Stack of RecursiveIterators来实现,在必要时调用它们getChildren()
。 RecursiveIteratorIterator的客户端实际上应该调用Iterator
和current()
之类的常规next()
方法...除了setMaxDepth()
您的问题是您尝试通过调用getChildren()
来自行进行递归。如果你想手动管理递归,那很好 - 但这会使RecursiveIteratorIterator
多余。事实上,我很惊讶在getChildren
上调用RecursiveIteratorIterator
()并没有致命的错误。这是RecursiveIterator
方法。 spl可能只是将方法调用转发给内部迭代器(一些spl类转发方法调用未定义的方法,以便于使用Decorator设计模式)。
正确的方式:
$dirItr = new RecursiveDirectoryIterator($path);
$filterItr = new Filter($dirItr);
$objects = new RecursiveIteratorIterator($filterItr, RecursiveIteratorIterator::SELF_FIRST);
$objects->setMaxDepth(self::MAX_DEPTH);
echo '<pre>';
foreach ($objects as $splFileInfo) {
echo $splFileInfo;
echo "\n";
}
我不打算在某些特定结构中为您构建分层数组,但也许这个相关问题可以进一步帮助您理解RecursiveIteratorIterator
和RecursiveIterator
之间的区别
How does RecursiveIteratorIterator work in PHP?