一个自定义PHP函数递归地迭代目录并输出一个分层的多维数组?
一个自定义PHP函数递归地迭代目录并输出一个分层的多维数组 使用新的SPL迭代器类(RecursiveIterator*),我一直在处理以下函数: 这将导致以下输出:一个自定义PHP函数递归地迭代目录并输出一个分层的多维数组?,php,arrays,recursion,multidimensional-array,iterator,Php,Arrays,Recursion,Multidimensional Array,Iterator,一个自定义PHP函数递归地迭代目录并输出一个分层的多维数组 使用新的SPL迭代器类(RecursiveIterator*),我一直在处理以下函数: 这将导致以下输出: Array ( [0] => Array ( [name] => Anchor Links [file] => anchor-links.php ) [1] => Array (
Array
(
[0] => Array
(
[name] => Anchor Links
[file] => anchor-links.php
)
[1] => Array
(
[name] => Columns
[file] => columns.php
)
[2] => Array
(
[name] => Page Layouts
[file] => page-layouts
[children] => Array
(
)
)
[page-layouts] => Array
(
[0] => Array
(
[name] => Right Sidebar
[file] => right-sidebar.php
)
[1] => Array
(
[name] => Left Sidebar
[file] => left-sidebar.php
)
[2] => Array
(
[name] => Right Sidebar
[file] => right-sidebar
[children] => Array
(
)
)
[right-sidebar] => Array
(
[0] => Array
(
[name] => Other Options
[file] => other-options.php
)
[1] => Array
(
[name] => Option A
[file] => option-a.php
)
[2] => Array
(
[name] => Other Options
[file] => other-options
[children] => Array
(
)
)
[other-options] => Array
(
[0] => Array
(
[name] => Sample
[file] => sample.php
)
)
)
[3] => Array
(
[name] => Changelog
[file] => changelog.php
)
)
)
然而,我试图实现的输出如下:
Array
(
[0] => Array
(
[name] => Anchor Links
[file] => anchor-links.php
)
[1] => Array
(
[name] => Columns
[file] => columns.php
)
[2] => Array
(
[name] => Page Layouts
[file] => page-layouts
[children] => Array
(
[0] => Array
(
[name] => Right Sidebar
[file] => right-sidebar.php
)
[1] => Array
(
[name] => Left Sidebar
[file] => left-sidebar.php
)
[2] => Array
(
[name] => Right Sidebar
[file] => right-sidebar
[children] => Array
(
[0] => Array
(
[name] => Other Options
[file] => other-options.php
)
[1] => Array
(
[name] => Option A
[file] => option-a.php
)
[2] => Array
(
[name] => Other Options
[file] => other-options
[children] => Array
(
[0] => Array
(
[name] => Sample
[file] => sample.php
)
)
)
)
)
[3] => Array
(
[name] => Changelog
[file] => changelog.php
)
)
)
)
我想我们就快到了,我只是在想如何让子目录输出到[children]中(现在)的空数组。另外,不要混淆重复或相似的名称(例如,同一目录中有一个right-sidebar.php文件和一个right-sidebar子目录)。如果您的目标是递归扫描给定目录(包括其子目录),并以分层方式返回包含所有文件夹和文件的多维数组,下面的函数:deepScan()可以帮助您 此函数只接受一个参数:
$directory
,它是要扫描的目录的路径。其他2个参数只是用于在递归过程中跟踪事物,因此应该单独使用
该函数返回一个多维数组,其中目录和子目录的名称作为键。每个子目录中的所有文件都列为该子目录的子目录
<?php
/**
* THIS FUNCTION SCANS A DIRECTORY "RECURSIVELY",
* BUILDING AN ARRAY TREE OF ALL FILES AND FOLDERS AS IT GOES...
* THIS IMPLIES THAT EVEN SUB-DIRECTORIES WILL BE SCANNED AS WELL
*
* FULL-PATH TO THE DIRECTORY TO SCAN
* @param $directory
*
* USED INTERNALLY DURING THE RECURSIVE TRIPS. LEAVE AS IS
* @param $k
*
* USED INTERNALLY DURING THE RECURSIVE TRIPS. LEAVE AS IS
* @param $key
*
* RETURNS THE RESULTING ARRAY
* @return array
*/
function deepScan($directory, &$k=null, $key=null) {
$iterator = new \DirectoryIterator ($directory);
$firstDir = basename($directory);
$dirs = [];
$dirs[$firstDir] = [];
if(!$key){ $key = $firstDir; }
if(!$k){ $k = &$dirs[$key]; }
if($k && $key){
$k[$key] = [];
$k = &$k[$key];
}
foreach($iterator as $info) {
$fileDirName = $info->getFilename();
if($info->isFile () && !preg_match("#^\..*?#", $fileDirName)){
$k[] = $directory . DIRECTORY_SEPARATOR . $fileDirName;
}else if($info->isDir() && !$info->isDot()){
$pathName = $directory . DIRECTORY_SEPARATOR . $fileDirName;
$k[$fileDirName] = $pathName;
$key = $fileDirName;
$it = &$k;
deepScan($pathName, $it, $key);
}
}
$dirs = removeEmptyEntries($dirs);
return $dirs;
}
/**
* THIS FUNCTION REMOVES/FILTERS EMPTY ENTRIES
* FROM THE RESULTING ARRAY TREE.
*
* THE ARRAY TO BE FILTERED
* @param $data
*
* RETURNS THE RESULTING FILTERED ARRAY
* @return array
*/
function removeEmptyEntries(array &$data){
foreach($data as $key=>&$item){
if(is_array($item)){
if(empty($item)) {
unset($data[$key]);
}else{
removeEmptyEntries($item);
}
}
}
foreach($data as $key=>&$item){
if(is_array($item) && empty($item)) {
unset($data[$key]);
}
}
return $data;
}
// USAGE:
$dirTree = deepScan( "/path_2_specific_directory" );
echo "<pre>";
print_r($dirTree);
echo "</pre>";
使用,以及一些参考杂耍,您可以通过一个显式循环来实现这一点
请注意这个标志recursivedirectoryinterator::SKIP_DOTS
它过滤掉
和。
文件
有一点很重要。使用应该可以避免使用显式嵌套循环。当您发现自己在这里使用显式嵌套循环时,您可能没有正确使用迭代器,或者迭代器本身不适合该任务(可能这是递归函数的域)。当然,总是存在边缘情况,但对于大多数情况,这条规则适用
<?php
/**
* THIS FUNCTION SCANS A DIRECTORY "RECURSIVELY",
* BUILDING AN ARRAY TREE OF ALL FILES AND FOLDERS AS IT GOES...
* THIS IMPLIES THAT EVEN SUB-DIRECTORIES WILL BE SCANNED AS WELL
*
* FULL-PATH TO THE DIRECTORY TO SCAN
* @param $directory
*
* USED INTERNALLY DURING THE RECURSIVE TRIPS. LEAVE AS IS
* @param $k
*
* USED INTERNALLY DURING THE RECURSIVE TRIPS. LEAVE AS IS
* @param $key
*
* RETURNS THE RESULTING ARRAY
* @return array
*/
function deepScan($directory, &$k=null, $key=null) {
$iterator = new \DirectoryIterator ($directory);
$firstDir = basename($directory);
$dirs = [];
$dirs[$firstDir] = [];
if(!$key){ $key = $firstDir; }
if(!$k){ $k = &$dirs[$key]; }
if($k && $key){
$k[$key] = [];
$k = &$k[$key];
}
foreach($iterator as $info) {
$fileDirName = $info->getFilename();
if($info->isFile () && !preg_match("#^\..*?#", $fileDirName)){
$k[] = $directory . DIRECTORY_SEPARATOR . $fileDirName;
}else if($info->isDir() && !$info->isDot()){
$pathName = $directory . DIRECTORY_SEPARATOR . $fileDirName;
$k[$fileDirName] = $pathName;
$key = $fileDirName;
$it = &$k;
deepScan($pathName, $it, $key);
}
}
$dirs = removeEmptyEntries($dirs);
return $dirs;
}
/**
* THIS FUNCTION REMOVES/FILTERS EMPTY ENTRIES
* FROM THE RESULTING ARRAY TREE.
*
* THE ARRAY TO BE FILTERED
* @param $data
*
* RETURNS THE RESULTING FILTERED ARRAY
* @return array
*/
function removeEmptyEntries(array &$data){
foreach($data as $key=>&$item){
if(is_array($item)){
if(empty($item)) {
unset($data[$key]);
}else{
removeEmptyEntries($item);
}
}
}
foreach($data as $key=>&$item){
if(is_array($item) && empty($item)) {
unset($data[$key]);
}
}
return $data;
}
// USAGE:
$dirTree = deepScan( "/path_2_specific_directory" );
echo "<pre>";
print_r($dirTree);
echo "</pre>";
function directoryToArray($directory)
{
$iterator = new RecursiveIteratorIterator(
new RecursiveDirectoryIterator(
$directory,
RecursiveDirectoryIterator::SKIP_DOTS
),
RecursiveIteratorIterator::SELF_FIRST
);
$files = [];
$references = [&$files];
foreach ($iterator as $item) {
$file = [
'name' => $item->getFilename(),
'file' => $item->getFilename(),
];
if ($item->isDir()) {
$file['children'] = [];
$references[$iterator->getDepth() + 1] =& $file['children'];
}
$references[$iterator->getDepth()][] = $file;
}
unset($references);
return $files;
}