0

SPL イテレータに関連するいくつかの質問 ( this onethis questionRecursiveIteratorIterator ) を見つけましたが、 ;のかなり高レベルの拡張機能を使用しているため、私の場合に役立つかどうかはわかりません。DirectoryTreeIterator。_

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 に答える