0

我发现了几个与 SPL 迭代器相关的问题(这个这个问题),但我不确定它们是否对我的情况有帮助,因为我使用的是 ; 的相当高级别的扩展RecursiveIteratorIteratorDirectoryTreeIterator. _

有人可以告诉我DirectoryTreeIterator在迭代器输出后如何更改或如何对每个目录返回的数组进行排序吗?

如果可以使用.htaccess例如,直接在 Apache 服务器上正确排序文件的方法对我来说也是一种选择。

这是DirectoryTreeIterator来自 SPL 的代码:

/** @file directorytreeiterator.inc
 * @ingroup Examples
 * @brief class DirectoryTreeIterator
 * @author  Marcus Boerger
 * @date    2003 - 2005
 *
 * SPL - Standard PHP Library
 */

/** @ingroup Examples
 * @brief   DirectoryIterator to generate ASCII graphic directory trees
 * @author  Marcus Boerger
 * @version 1.1
 */

class DirectoryTreeIterator extends RecursiveIteratorIterator
{
    /** Construct from a path.
     * @param $path directory to iterate
     */
    function __construct($path) {
        parent::__construct(
            new RecursiveCachingIterator(
                new RecursiveDirectoryIterator($path, RecursiveDirectoryIterator::KEY_AS_FILENAME
                ), 
                CachingIterator::CALL_TOSTRING|CachingIterator::CATCH_GET_CHILD
            ), 
            parent::SELF_FIRST
        );
    }

    /** @return the current element prefixed with ASCII graphics
     */ 
    function current() {
        $tree = '';
        for ($l=0; $l < $this->getDepth(); $l++) {
            $tree .= $this->getSubIterator($l)->hasNext() ? ' ' : ' ';
        }
        return $tree . ($this->getSubIterator($l)->hasNext() ? ' ' : ' ') 
               . $this->getSubIterator($l)->__toString();
    }

    /** Aggregates the inner iterator
     */ 
    function __call($func, $params) {
        return call_user_func_array(array($this->getSubIterator(), $func), $params);;
    }
}

澄清为什么我使用上面的代码是因为它完全符合我的需求。我想生成一个以空格为前缀的递归目录树——Marcus Boerger 的原始代码示例添加了一些 ASCI 元素。问题是我无法控制文件和目录的排序,所以我希望目录树看起来像这样:

dir001
  subdir001
    subdir002
      subfile001.jpg
  file001.png
  file002.png
  file003.png
dir002
  apple.txt
  bear.txt
  contact.txt
dir003
[...]

相反,迭代器返回的列表根本没有排序,它向我显示了如下内容:

dir002
  bear.txt
  apple.txt
  contact.txt
dir001
  subdir001
    subdir002
      subfile001.jpg
  file002.png
  file001.png
  file003.png
dir003
[...]

所以我想我正在寻找的解决方案是每次索引子目录并添加到目录树时调用排序方法的某种方式。

我希望我已经把它说得更清楚了,作为一个非母语的人,有时很难将想法变成连贯的句子(甚至是单词)。

4

2 回答 2

3

好吧,我不确定你从哪里得到这个课程,但它正在做一些非常混乱的事情(至少可以说包括一些错误)。虽然它使用 SPL,但它不是 SPL 类。

现在,我不是 100% 确定您所说的“排序”是什么意思,但是假设您在谈论自然排序,为什么不只是展平数组,然后对其进行排序呢?

$it = new RecursiveTreeIterator(
    new RecrusiveDirectoryIterator($dir),
    RecursiveTreeIterator::BYPASS_KEY,
    CachingIterator::CALL_TOSTRING
);
$files = iterator_to_array($it);
natsort($files);
echo implode("\n", $files);

或者

$it = new RecursiveIteratorIterator(
    new RecursiveDirectoryIterator($dir),
    RecursiveIteratorIterator::SELF_FIRST
);
$files = iterator_to_array($it);
$files = array_map(function($file) { return (string) $file; }, $files);
natsort($files);
echo implode("\n", $files);

编辑:根据您的编辑,这是我将如何解决它:

function BuildTree($it, $separator = '  ', $level = '') {
    $results = array();
    foreach ($it as $file) {
        if (in_array($file->getBasename(), array('.', '..'))) {
            continue;
        }
        $tmp = $level . $file->getBaseName();
        if ($it->hasChildren()) {
            $newLevel = $level . $separator;
            $tmp .= "\n" . BuildTree($it->getChildren(), $separator, $newLevel);
        }
        $results[] = $tmp;
    }
    natsort($results);
    return implode("\n", $results);
};
$it = new RecursiveDirectoryIterator($dir);
$tree = BuildTree($it);

这是一个非常简单的递归解析器,并且在每个级别上进行自然排序。

于 2011-03-24T10:44:26.813 回答
0

不了解 SPL 迭代器,但对于您的迭代器,您应该将项目放在一个数组中,然后对它们进行排序并将它们添加到 $tree。我修改了函数current但没有测试它:

function current()
{
    $tree = '';

    $treeitems = array();
    for ($l=0; $l < $this->getDepth(); $l++) {
        //NOTE: On this line I think you have an error in your original code:
        //      This ? ' ' : ' ' is strange
        $treeitems[] = $this->getSubIterator($l)->hasNext() ? ' ' : ' ';
    }
    $treeitems.sort();
    for each ($treeitems as $treeitem)
        $tree .= $treeitem;

    return $tree . ($this->getSubIterator($l)->hasNext() ? ' ' : ' ') 
           . $this->getSubIterator($l)->__toString();
}
于 2011-03-24T10:28:32.120 回答