使用RecursiveDirectoryTerator生成子目录的嵌套数组


Make a nested array of subdirectories using RecursiveDirectoryIterator

我有以下目录结构

test
  directory_in_test
    directory_in_directory_in_test
  directory2_in_test
    directory_in_directory2_in_test
  abc.php
index.php

我正在尝试制作一个函数,该函数将提供子目录的多维数组。所需输出类似于:

[directories] => Array(
    [test] => Array(
        [directory_in_test] => Array(
            [directory_in_directory_in_test] => null
        )
        [directory2_in_test] => Array(
            [directory_in_directory2_in_test] => null
        )      
    )
)

我曾尝试将RecursiveIteratorIteratorRecursiveDirectoryIterator一起使用,但它提供了一个目录和文件的一级数组,这与我的要求相去甚远。这是代码和结果我有

代码

<?php
    public function findDirectories($path = '', $like = '')
    {
        $path = (is_dir($path)) ? $path : getcwd();
        $directories = array();
        $iterator = new 'RecursiveIteratorIterator(new 'RecursiveDirectoryIterator($path));
        foreach ($iterator as $directory) {
            if($directory->isDir())
                $directories[] = $directory->getPathName();
        }
        return $directories;
    }

打印$directories的结果

Array
(
    [0] => D:'xampp'htdocs'raheelwp'file-resolver'tests'.
    [1] => D:'xampp'htdocs'raheelwp'file-resolver'tests'..
    [2] => D:'xampp'htdocs'raheelwp'file-resolver'tests'directory2_in_test'.
    [3] => D:'xampp'htdocs'raheelwp'file-resolver'tests'directory2_in_test'..
    [4] => D:'xampp'htdocs'raheelwp'file-resolver'tests'directory2_in_test'directory_in_directory2_in_test'.
    [5] => D:'xampp'htdocs'raheelwp'file-resolver'tests'directory2_in_test'directory_in_directory2_in_test'..
    [6] => D:'xampp'htdocs'raheelwp'file-resolver'tests'directory_in_test'.
    [7] => D:'xampp'htdocs'raheelwp'file-resolver'tests'directory_in_test'..
    [8] => D:'xampp'htdocs'raheelwp'file-resolver'tests'directory_in_test'direcotry_in_directory_in_test'.
    [9] => D:'xampp'htdocs'raheelwp'file-resolver'tests'directory_in_test'direcotry_in_directory_in_test'..
) 
<?php
$it = new RecursiveDirectoryIterator(".", RecursiveDirectoryIterator::SKIP_DOTS);
$it = new RecursiveIteratorIterator($it);
$files = new RecursiveArrayIterator(array());
foreach ($it as $fi) {
    $it = $files;
    $dirs = explode('/', $fi->getPath());
    foreach ($dirs as $path) {
        if (isset($it[$path])) {
            $it = $it[$path];
        } else {
            $it[$path] = new RecursiveArrayIterator();
        }
    }
    $it[$fi->getFileName()] = $fi->getFileName();
}

$a = array();
createArray($a, $files);
print_r($a);
function createArray(&$a, $it) {
    foreach ($it as $k => $tmp) {
        if (is_string($tmp)) {
            $a[] = $tmp;
        } else {
            $a[$k] = array();
            createArray($a[$k], $tmp);
        }
    }
}

代码相当简单,可以分为两部分,尽管只需一部分就可以轻松创建。第一部分将把目录拆分为单独的RecursiveArrayIterators,因此您可以保留"迭代器"功能来完成所有其他工作。当您开始使用SPL迭代器时,这通常很有用。

第二部分,createArray函数基本上使用数组引用来指向"当前"目录。由于它将是一个多维数组,我们不必担心我们实际在数组中的"位置"(它可能是第1级,如果您的目录结构深入到第100级,也可能是第100级)。它只是检查给定的元素是否是字符串,如果是,则是文件,否则是目录,因此我们再次递归调用createArray

可能是更简单的解决方案,但我认为大多数都使用了基本的数组引用系统。