使用RecursiveDirectoryIterator创建嵌套的子目录数组

时间:2015-04-04 14:19:28

标签: php recursion foreach spl

我有以下目录结构

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;
    }

打印$目录的结果

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\..
) 

1 个答案:

答案 0 :(得分:0)

<?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函数基本上使用数组引用指向“当前”目录。因为它将是一个多维数组,所以我们不必担心数组中的“where”(它可能是第一级,如果你的目录结构那么深,它也可能是第100级)。它只是检查给定元素是否是一个字符串,如果是,它是一个文件,否则它是一个目录,所以我们再次递归调用createArray

可能是更简单的解决方案,但我认为大多数都使用基本的阵列参考系统。