RecursiveDirectoryIterator 缩进子文件夹
RecursiveDirectoryIterator indent subfolders
我使用 RecursiveDirectoryIterator
列出了我所有的文件和文件夹,我想以与资源管理器相同的方式显示结果。
为此,我需要缩进子文件夹,但我不知道该怎么做......
我可以使用子文件夹计数器,但它只适用于级别 1,对于级别 2 它不起作用...
这是我的代码:
$nb=1;
$read_folder = './cases/';
$iterator = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($read_folder), RecursiveIteratorIterator::SELF_FIRST);
foreach ($iterator as $file) {
$nb++;
if ($file->isDir()) {
$list_docs .= '<li class="docResult"><i class="fa fa-folder"></i> <span id="file_'.$nb.'">'.$file->getFilename().'</span></li>';
} else {
$list_docs .= '<li class="docResult"><i class="fa fa-file-o"></i> <span id="file_'.$nb.'">'.$file->getFilename().'</span></li>';
}
}
这是遍历目录树的程序的版本 2。
它必须是一个不同的程序,因为需要对输出进行排序,以便在文件之前打印目录和打印。
现在,当我开始寻找答案时,它似乎很简单。嗯...;-/
我最终得出结论,我要么必须使用现成的包,例如 synfony : The Finder Component,要么编写我自己的 Directory iterator
组件。
后者我做了,自己做了SortedDirectory
class.
输出没有任何格式。它使用浏览器的默认样式。
class SortedDirectory 的源代码可用。
代码:
<?php //
include 'Q31470421-sorted-directory-class.php';
$sourceFolder = 'P:\developer\xampp\htdocs\testmysql\Q23408272'; // top level directory to search
// $sourceFolder = 'P:\developer\xampp\htdocs\testmysql'; // top level directory to search
/**
* Sorted Directory for the supplied path
*/
$dirIter = new SortedDirectory(new SplFileInfo($sourceFolder));
/**
* Process the complete path recursing around as required..
*/
echo processDirectory($dirIter);
exit; // end the program
/**
* Recurse around all the paths
*
* @param \SortedDirectory $directory
*/
function processDirectory(\SortedDirectory $directory, $depth = 0)
{
$html = showOneDirectory($directory, $depth); // show all files in this directory
foreach ($directory as $entry) {
if ($entry->isDir()) { // recurse arount any sub-directories
$html .= '<ul class="dir-start">';
$html .= processDirectory(new \SortedDirectory($entry), $depth + 1);
$html .= '<!-- dir-end --></ul>';
}
}
return $html;
}
/**
* Process all the files for one directory
*
* @param \SortedDirectory $directory
* @param type $depth
* @return html
*/
function showOneDirectory(\SortedDirectory $directory, $depth = 0)
{
$dirCount = 0;
$fileCount = 0;
$list_docs = '<ul>';
foreach ($directory as $key => $entry) {
if ($entry->isDir()) {
$dirCount++;
$list_docs .= '<li class="docResult">'
.'<i class="fa fa-folder">'
.'</i> <span id="file_'. $key .'">'
.' Directory: '
.' Name: '. $entry->getFilename()
.' | Path: '. $entry->getPath()
.' | Depth: '. $depth
.'</span></li>';
}
else {
$fileCount++;
$list_docs .= '<li class="docResult">'
.'<i class="fa fa-folder">'
.'</i> <span id="file_'. $key .'">'
.' File: '
.' Name: '. $entry->getFilename()
.' | Path: '. $entry->getPath()
.' | Depth: '. $depth
.'</span></li>';
}
}
$list_docs .= '<li>'. "Counts: Dir: $dirCount, Files: $fileCount" .'</li>';
return $list_docs .= '</ul>';
}
SortedDirectory
class:
如果您想更改排序顺序,请编辑:
private function cmpEntry(SplFileInfo $entry1, SplFileInfo $entry2)
<?php //
// Q31470421-sorted-directory-class
class SortedDirectory implements IteratorAggregate, Countable
{
/**
* Sorted directory list
*
* @var array
*/
private $directories = array();
/**
* sorted file list
*
* @var array
*/
private $files = array();
private $allFiles = null;
/**
* Read the supplied directory into the two lists and sort them
*
* Ignore the '.' and '..' entries
*
* @param SplFileInfo
*/
public function __construct(\SplFileInfo $directory)
{
foreach (new DirectoryIterator($directory->getRealPath()) as $entry) {
if ($entry->isDir()) {
$fname = $entry->getBasename();
if (substr($fname, 0, 1) === '.') {
if ($fname === '.' || $fname === '..') {
continue;
}
}
$this->directories[] = clone $entry;
}
else {
$this->files[] = clone $entry;
}
}
$this->sortLists();
}
/**
* Iterator of the sorted directory list
*
* @return \ArrayIterator
*/
public function getDirIterator()
{
return new ArrayIterator($this->directories);
}
/**
* Iterator of the sorted files
*
* @return \ArrayIterator
*/
public function getFileIterator()
{
return new ArrayIterator($this->files);
}
/**
* Iterator of all the directory entries
*
* @return \ArrayIterator All the files with directories before files
*/
public function getIterator()
{
return new ArrayIterator($this->allFiles);
}
public function __get($property)
{
return $this->$property;
}
/*
* Implement Iterator
*
*/
/**
* @return \SplFileInfo
*/
public function current()
{
return current($this->allFiles);
}
/**
* @return int
*/
public function key()
{
return key($this->allFiles);
}
public function next()
{
return next($this->allFiles);
}
public function reset()
{
return reset($this->allFiles);
}
public function rewind()
{
return reset($this->allFiles);
}
public function valid()
{
return current($this->allFiles) !== false;
}
/**
* @return integer
*/
public function count()
{
return count($this->allFiles);
}
/**
* Sort lists using 'natural' compare
*/
private function sortLists()
{
if (count($this->directories) >= 2) {
usort($this->directories, array($this, 'cmpEntry'));
}
if (count($this->files) >= 2) {
usort($this->files, array($this, 'cmpEntry'));
}
$this->allFiles = array_merge($this->directories, $this->files);
}
private function cmpEntry(SplFileInfo $entry1, SplFileInfo $entry2)
{
return strnatcasecmp($entry1->getFilename(), $entry2->getFilename());
}
}
为了记录,我已经将 class (RecursiveDirectoryIterator
) 变成了一个要点,它可以读取一个目录及其所有子目录并输出一个 JSON 或一个数组。
https://gist.github.com/jonataswalker/3c0c6b26eabb2e36bc90
以及输出的树查看器
我使用 RecursiveDirectoryIterator
列出了我所有的文件和文件夹,我想以与资源管理器相同的方式显示结果。
为此,我需要缩进子文件夹,但我不知道该怎么做......
我可以使用子文件夹计数器,但它只适用于级别 1,对于级别 2 它不起作用...
这是我的代码:
$nb=1;
$read_folder = './cases/';
$iterator = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($read_folder), RecursiveIteratorIterator::SELF_FIRST);
foreach ($iterator as $file) {
$nb++;
if ($file->isDir()) {
$list_docs .= '<li class="docResult"><i class="fa fa-folder"></i> <span id="file_'.$nb.'">'.$file->getFilename().'</span></li>';
} else {
$list_docs .= '<li class="docResult"><i class="fa fa-file-o"></i> <span id="file_'.$nb.'">'.$file->getFilename().'</span></li>';
}
}
这是遍历目录树的程序的版本 2。
它必须是一个不同的程序,因为需要对输出进行排序,以便在文件之前打印目录和打印。
现在,当我开始寻找答案时,它似乎很简单。嗯...;-/
我最终得出结论,我要么必须使用现成的包,例如 synfony : The Finder Component,要么编写我自己的 Directory iterator
组件。
后者我做了,自己做了SortedDirectory
class.
输出没有任何格式。它使用浏览器的默认样式。
class SortedDirectory 的源代码可用。
代码:
<?php //
include 'Q31470421-sorted-directory-class.php';
$sourceFolder = 'P:\developer\xampp\htdocs\testmysql\Q23408272'; // top level directory to search
// $sourceFolder = 'P:\developer\xampp\htdocs\testmysql'; // top level directory to search
/**
* Sorted Directory for the supplied path
*/
$dirIter = new SortedDirectory(new SplFileInfo($sourceFolder));
/**
* Process the complete path recursing around as required..
*/
echo processDirectory($dirIter);
exit; // end the program
/**
* Recurse around all the paths
*
* @param \SortedDirectory $directory
*/
function processDirectory(\SortedDirectory $directory, $depth = 0)
{
$html = showOneDirectory($directory, $depth); // show all files in this directory
foreach ($directory as $entry) {
if ($entry->isDir()) { // recurse arount any sub-directories
$html .= '<ul class="dir-start">';
$html .= processDirectory(new \SortedDirectory($entry), $depth + 1);
$html .= '<!-- dir-end --></ul>';
}
}
return $html;
}
/**
* Process all the files for one directory
*
* @param \SortedDirectory $directory
* @param type $depth
* @return html
*/
function showOneDirectory(\SortedDirectory $directory, $depth = 0)
{
$dirCount = 0;
$fileCount = 0;
$list_docs = '<ul>';
foreach ($directory as $key => $entry) {
if ($entry->isDir()) {
$dirCount++;
$list_docs .= '<li class="docResult">'
.'<i class="fa fa-folder">'
.'</i> <span id="file_'. $key .'">'
.' Directory: '
.' Name: '. $entry->getFilename()
.' | Path: '. $entry->getPath()
.' | Depth: '. $depth
.'</span></li>';
}
else {
$fileCount++;
$list_docs .= '<li class="docResult">'
.'<i class="fa fa-folder">'
.'</i> <span id="file_'. $key .'">'
.' File: '
.' Name: '. $entry->getFilename()
.' | Path: '. $entry->getPath()
.' | Depth: '. $depth
.'</span></li>';
}
}
$list_docs .= '<li>'. "Counts: Dir: $dirCount, Files: $fileCount" .'</li>';
return $list_docs .= '</ul>';
}
SortedDirectory
class:
如果您想更改排序顺序,请编辑:
private function cmpEntry(SplFileInfo $entry1, SplFileInfo $entry2)
<?php //
// Q31470421-sorted-directory-class
class SortedDirectory implements IteratorAggregate, Countable
{
/**
* Sorted directory list
*
* @var array
*/
private $directories = array();
/**
* sorted file list
*
* @var array
*/
private $files = array();
private $allFiles = null;
/**
* Read the supplied directory into the two lists and sort them
*
* Ignore the '.' and '..' entries
*
* @param SplFileInfo
*/
public function __construct(\SplFileInfo $directory)
{
foreach (new DirectoryIterator($directory->getRealPath()) as $entry) {
if ($entry->isDir()) {
$fname = $entry->getBasename();
if (substr($fname, 0, 1) === '.') {
if ($fname === '.' || $fname === '..') {
continue;
}
}
$this->directories[] = clone $entry;
}
else {
$this->files[] = clone $entry;
}
}
$this->sortLists();
}
/**
* Iterator of the sorted directory list
*
* @return \ArrayIterator
*/
public function getDirIterator()
{
return new ArrayIterator($this->directories);
}
/**
* Iterator of the sorted files
*
* @return \ArrayIterator
*/
public function getFileIterator()
{
return new ArrayIterator($this->files);
}
/**
* Iterator of all the directory entries
*
* @return \ArrayIterator All the files with directories before files
*/
public function getIterator()
{
return new ArrayIterator($this->allFiles);
}
public function __get($property)
{
return $this->$property;
}
/*
* Implement Iterator
*
*/
/**
* @return \SplFileInfo
*/
public function current()
{
return current($this->allFiles);
}
/**
* @return int
*/
public function key()
{
return key($this->allFiles);
}
public function next()
{
return next($this->allFiles);
}
public function reset()
{
return reset($this->allFiles);
}
public function rewind()
{
return reset($this->allFiles);
}
public function valid()
{
return current($this->allFiles) !== false;
}
/**
* @return integer
*/
public function count()
{
return count($this->allFiles);
}
/**
* Sort lists using 'natural' compare
*/
private function sortLists()
{
if (count($this->directories) >= 2) {
usort($this->directories, array($this, 'cmpEntry'));
}
if (count($this->files) >= 2) {
usort($this->files, array($this, 'cmpEntry'));
}
$this->allFiles = array_merge($this->directories, $this->files);
}
private function cmpEntry(SplFileInfo $entry1, SplFileInfo $entry2)
{
return strnatcasecmp($entry1->getFilename(), $entry2->getFilename());
}
}
为了记录,我已经将 class (RecursiveDirectoryIterator
) 变成了一个要点,它可以读取一个目录及其所有子目录并输出一个 JSON 或一个数组。
https://gist.github.com/jonataswalker/3c0c6b26eabb2e36bc90
以及输出的树查看器