Сортировка файлов по каталогу с помощью каталога DirectoryTreeIterator

Я нашел пару вопросов ( этот и этот вопрос ), связанные с итераторами SPL, но я не уверен, насколько они полезны в моем случае, поскольку я использую довольно высокий уровень расширения RecursiveIteratorIterator ; DirectoryTreeIterator .

Может ли кто-нибудь, возможно, показать мне, как изменить DirectoryTreeIterator или как отсортировать возвращаемый массив по каталогу после того, как он был выведен итератором?

Метод сортировки файлов правильно на сервере Apache также является для меня вариантом, если это возможно, например, с использованием .htaccess .

Это код 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);; } } 

Чтобы уточнить, почему я использую приведенный выше код, это потому, что он точно соответствует моим потребностям. Я хочу создать рекурсивное дерево каталогов, префиксное пробелами – пример исходного кода Маркуса Боергера добавляет некоторые элементы 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 [...] 

Поэтому я предполагаю, что решение, которое я ищу, – это способ вызова метода сортировки каждый раз, когда подкаталог индексируется и добавляется в дерево каталогов.

Надеюсь, что я сделал это несколько яснее, как неродного оратора, иногда трудно вставлять мысли в последовательные предложения (или даже слова, если на то пошло).

Ну, я не уверен, откуда вы взяли этот класс, но он делает некоторые избитые вещи (в том числе несколько ошибок, если не сказать больше). И хотя он использует 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); 

Это довольно простой рекурсивный синтаксический анализатор и делает естественный вид на каждом уровне.

Не знаю о итераторах SPL, но для вашего итератора вы должны поместить элементы в массив, затем отсортировать их и добавить их в $ tree. Я изменил функцию тока, но не тестировал его:

 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(); }