У меня есть функция, которая будет получать все каталоги и файлы из данного каталога, однако способ их получения делает работу немного сложнее:
function getFileLists($dir, $recursive=FALSE) {
// retrieve an array of all the directories and files in a certain directory
$retval = [];
if (substr($dir, -1) !== "/") {
$dir .= "/";
}
$d = @dir($dir) or die("unable to open {$dir} for reading, permissions?");
while(FALSE !== ($entry = $d->read())) {
if ($entry{0} === ".") { continue; }
if (is_dir("{$dir}{$entry}")) {
$retval[] = [
'name' => "{$dir}{$entry}",
'last_modified' => filemtime("{$dir}{$entry}")
];
if($recursive && is_readable("{$dir}{$entry}/")) {
$retval = array_merge($retval, getFileLists("{$dir}{$entry}/", TRUE));
}
} elseif (is_readable("{$dir}{$entry}")) {
$retval[] = [
'name' => "{$dir}{$entry}",
'last_modified' => filemtime("{$dir}{$entry}")
];
}
}
$d->close();
return $retval;
}
Когда вы запустите это в заданном каталоге, вы получите следующие результаты:
array(14) {
[0]=>
array(2) {
["name"]=>
string(15) "./kb_data/admin"["last_modified"]=>
int(1543591247)
}
[1]=>
array(2) {
["name"]=>
string(28) "./kb_data/admin/testfile.txt"["last_modified"]=>
int(1543591238)
}
...
}
Это замечательно, но из-за этого довольно сложно работать, поскольку я хочу отобразить этот каталог как tree
, Что я на самом деле хочу сделать, так это произвести что-то вроде следующего:
array(14) {
[0]=>
array(3) {
["name"]=>
string(16) "./kb_data/shared"["last_modified"]=>
int(1543591258)
["files"] => array(#) {
["name"]=>
string(29) "./kb_data/shared/testfile.txt"["last_modified"]=>
int(1543591238)
}
}
...
}
Как видите, я хочу, чтобы каждый файл в каталоге находился внутри каталога. Как я могу провести рефакторинг этой функции, чтобы получить желаемый результат?
Как насчет (SPL) Директора Итератор
function getFileLists($dir) {
$rec = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($dir), RecursiveIteratorIterator::SELF_FIRST);
$ar = array();
foreach ($rec as $splFileInfo) {
$path = $splFileInfo->isDir()
? array($splFileInfo->getFilename() => array())
: array($splFileInfo->getFilename());
for ($depth = $rec->getDepth() - 1; $depth >= 0; $depth--) {
$path = array($rec->getSubIterator($depth)->current()->getFilename() => $path);
}
$ar = array_merge_recursive($ar, $path);
}
return $ar;
}
print "<pre>";
print_r(getFileLists("/Library/WebServer/Documents/am-web/"));
Лично мне нравится быть простым, вытащил это из моей личной библиотеки,
возможно, не самый лучший ответ, но он добился цели
<?php
function glob_recursive($dir, $recursive = false) {
$files = [];
foreach (glob($dir . DIRECTORY_SEPARATOR . '*') as $object) {
if (in_array($object, ['.', '..'])) {
continue;
}
$file = [];
$file['name'] = $object;
if (false !== $recursive && is_dir($object)) {
$file['files'] = glob_recursive($object);
}
$files[] = $file;
}
return $files;
}
$dir = __DIR__;
$list = glob_recursive($dir);
Простой, но полный пример, который использует DirectoryIterator
перечислить все файлы в каталоге и рекурсии, чтобы избежать необходимости манипулировать рекурсивными данными итератора, чтобы получить всю необходимую информацию. То, что мне нравится в DirectoryIterator
является то, что это дает объект, где вы можете извлечь много деталей файлов (например, время последнего изменения, используя getMTime()
).
function buildTree ( $path ) {
$paths = [];
foreach (new DirectoryIterator ($path) as $file) {
if ( !$file->isDot() ) {
$newFile = ["name" => $file->getRealPath(),
"last_modified" => $file->getMTime()];
if ($file->isDir()) {
$newFile["files"] = buildTree($file->getRealPath());
}
$paths[] = $newFile;
}
}
return $paths;
}
$paths = buildTree($root);
Я бы удалил параметр «recursive» и попробовал что-то вроде этого:
function getFileLists($dir)
{
echo "Processing $dir\n";
// retrieve an array of all the directories and files in a certain directory
$retval = [];
if (substr($dir, -1) !== "/") {
$dir .= "/";
}
$d = @dir($dir) or die("unable to open {$dir} for reading, permissions?");
while (false !== ($entry = $d->read())) {
if ($entry{0} === ".") {
continue;
}
if (is_dir("{$dir}{$entry}")) {
$retval[] = [
'name' => "{$dir}{$entry}",
'last_modified' => filemtime("{$dir}{$entry}"),
//recursive call
'files' => array_merge($retval, getFileLists("{$dir}{$entry}/"))
];
} elseif (is_readable("{$dir}{$entry}")) {
$retval[] = [
'name' => "{$dir}{$entry}",
'last_modified' => filemtime("{$dir}{$entry}")
];
}
}
$d->close();
return $retval;
}