Sort directory listing using RecursiveDirectoryIterator
I'm using RecursiveDirectoryIterator
and RecursiveIteratorIterator
to build a file listing tree using code like below. I need to the list to be sorted - either directories then files alphabetically, or just alphabetically.
Can anyone tell me ho开发者_运维百科w to sort the file list?
$dir_iterator = new RecursiveDirectoryIterator($groupDirectory);
$iterator = new RecursiveIteratorIterator($dir_iterator, RecursiveIteratorIterator::SELF_FIRST);
foreach ($iterator as $file) {
// do stuff with $file
}
There are multiple options available, which you can use to sort an iterator in one way or another. The best option would depend a great deal on precisely how you want to manipulate the iterator contents, what you want to get out of the iterator and indeed how much or little of the iterator you really want/need.
Approaches would vary; making use of classes like SplHeap
(or Min
, Max
varieties), SplPriorityQueue
(maybe for things like file size) or just wrapping your iterator in something like ArrayObject
which can sort its own contents.
I'll use an SplHeap
as an example. Since you want to arrange the entire contents of the RecursiveDirectoryIterator
alphabetically then something like the following could be used:
class ExampleSortedIterator extends SplHeap
{
public function __construct(Iterator $iterator)
{
foreach ($iterator as $item) {
$this->insert($item);
}
}
public function compare($b,$a)
{
return strcmp($a->getRealpath(), $b->getRealpath());
}
}
$dit = new RecursiveDirectoryIterator("./path/to/files");
$rit = new RecursiveIteratorIterator($dit);
$sit = new ExampleSortedIterator($rit);
foreach ($sit as $file) {
echo $file->getPathname() . PHP_EOL;
}
The sorting order is alphabetical, mixing files and folders:
./apple
./apple/alpha.txt
./apple/bravo.txt
./apple/charlie.txt
./artichoke.txt
./banana
./banana/aardvark.txt
./banana/bat.txt
./banana/cat.txt
./beans.txt
./carrot.txt
./cherry
./cherry/amy.txt
./cherry/brian.txt
./cherry/charlie.txt
./damson
./damson/xray.txt
./damson/yacht.txt
./damson/zebra.txt
./duck.txt
This is not possible using the Iterator itself. I have seen an extension to the Iterator
class somewhere on SO that did sorting but remember hazily to have had trouble with it.
Maybe the answers to this question help, even though they point away from the Iterator?
Update: Here is a dupe to your question with some answers - admittedly not many, though!
Sönke Ruempler has a great solution:
class SortingIterator implements IteratorAggregate
{
private $iterator = null;
public function __construct(Traversable $iterator, $callback)
{
if (!is_callable($callback)) {
throw new InvalidArgumentException('Given callback is not callable!');
}
$array = iterator_to_array($iterator);
usort($array, $callback);
$this->iterator = new ArrayIterator($array);
}
public function getIterator()
{
return $this->iterator;
}
}
Source: https://ruempler.eu/2008/08/09/php-sortingiterator/
精彩评论