【问题标题】:Deep recursive array of directory structure in PHPPHP中目录结构的深度递归数组
【发布时间】:2010-10-31 10:29:09
【问题描述】:

我正在尝试将我硬盘上的一些文件夹放入一个数组中。

例如,度假照片。 假设我们有这样的结构:

  • 设置 1
    • 第 1 组的第 1 项
    • 第 1 组第 2 项
    • 第 1 组的项目 ...
  • 设置 2
    • 第 2 组的子集 1
      • 第 2 组子集 1 的第 1 项
      • 第 2 组子集 1 的项目 ...
    • 第 2 组的子集 2
    • 随机文件,不是目录。
  • 设置 3
  • ...

我想要这样的东西,作为一个数组。
意思是我有 1 个大数组,并且在那个数组中有更多的数组。每个集合和子集都有自己的数组。

我试图让它看起来像这样:

Array
(
    [Set 1] => Array([0] => Item 1 of Set 1, [1] => Item 1 of Set 1,...)
    [Set 2] => Array([Subnet 1] => Array([0] => Item 1 of Subset 1 of Set 2,[1] => ...), [Subnet 2] => Array([0] => ..., ..., ...), ..., [0] => Random File)
    [set 3] => Array(...)
    ...
)

我遇到了这个:http://www.the-art-of-web.com/php/dirlist/

但这不是我想要的。我一直在干预它,但它给我带来的只是麻烦。

这是一个示例,查看更大分辨率的源代码(显然没有点击...)。

【问题讨论】:

  • 这个问题不是重复的,不应该这样标记。

标签: php arrays recursion


【解决方案1】:

我建议使用DirectoryIterator 来构建您的阵列

这是我快速拼凑的一个 sn-p,但我目前没有测试它的环境,所以准备调试它。

$fileData = fillArrayWithFileNodes( new DirectoryIterator( '/path/to/root/' ) );

function fillArrayWithFileNodes( DirectoryIterator $dir )
{
  $data = array();
  foreach ( $dir as $node )
  {
    if ( $node->isDir() && !$node->isDot() )
    {
      $data[$node->getFilename()] = fillArrayWithFileNodes( new DirectoryIterator( $node->getPathname() ) );
    }
    else if ( $node->isFile() )
    {
      $data[] = $node->getFilename();
    }
  }
  return $data;
}

【讨论】:

  • 我收到此错误:致命错误:达到“100”的最大函数嵌套级别,正在中止!而且我不明白为什么我应该得到这个......我拥有的最高嵌套是 5 层。
  • 好的,我有机会运行它并修复了错误 - 再试一次。
  • 现在发生的事情是,每当我转到一个新的主文件夹时,旧文件夹都会被覆盖。
  • 您的原始问题询问如何递归遍历目录树并将该数据加载到数组中 - 我的答案就是这样做的。如果您期待更多内容,则必须提供更多详细信息。
  • Peter 的解决方案看起来与您的白板显示的完全一样。有什么问题?
【解决方案2】:

没有任何错误处理的简单实现:

function dirToArray($dir) {
    $contents = array();
    # Foreach node in $dir
    foreach (scandir($dir) as $node) {
        # Skip link to current and parent folder
        if ($node == '.')  continue;
        if ($node == '..') continue;
        # Check if it's a node or a folder
        if (is_dir($dir . DIRECTORY_SEPARATOR . $node)) {
            # Add directory recursively, be sure to pass a valid path
            # to the function, not just the folder's name
            $contents[$node] = dirToArray($dir . DIRECTORY_SEPARATOR . $node);
        } else {
            # Add node, the keys will be updated automatically
            $contents[] = $node;
        }
    }
    # done
    return $contents;
}

【讨论】:

  • 这里发生的情况是目录列表被展平,所有文件一个接一个地列出。
  • 我刚刚运行了我的音乐合辑的一部分,按预期工作。
  • 我知道这是旧的,但这正是我想要的正是。完美。谢谢!
  • 非常好,是的。我做了一些小的调整。大多数时候使用DIRECTORY_ITERATOR 并不是必需的。哦,男孩,评论编辑器不会让我格式化。啊。我会用我的 sn-p 在下面添加一个答案。
  • @tim 只是提醒一下,@soulmerge 的代码中没有 DIRECTORY_ITERATOR...(DIRECTORY_SEPARATOR ≠ DIRECTORY_ITERATOR)
【解决方案3】:

基于@soulmerge's answer的代码。我刚刚删除了一些 nits 和 cmets 并使用 $startpath 作为我的起始目录。 (谢谢@soulmerge!)

function dirToArray($dir) {
    $contents = array();
    foreach (scandir($dir) as $node) {
        if ($node == '.' || $node == '..') continue;
        if (is_dir($dir . '/' . $node)) {
            $contents[$node] = dirToArray($dir . '/' . $node);
        } else {
            $contents[] = $node;
        }
    }
    return $contents;
}

$r = dirToArray($startpath);
print_r($r);

【讨论】:

    【解决方案4】:

    我已经成功使用 PEAR File_Find 包,特别是 the mapTreeMultiple() method。你的代码会变成这样:

    require_once 'File/Find.php';
    $fileList = File_Find::mapTreeMultiple($dirPath);
    

    这应该返回一个类似于您要求的数组。

    【讨论】:

    • 这个“文件/Find.php”文件是什么?我已经扫描了我的硬盘驱动器,但上面没有这样的文件。我确实安装了 PEAR。可能是我使用的是 Windows。
    【解决方案5】:

    所以 6 年后......

    我需要像 @tim 和 @soulmerge 的答案那样的解决方案。我试图为默认 codeigniter 文件夹中的所有 php 文件做批量 php UnitTest 模板。

    这是我过程中的第一步,将目录/文件夹的完整递归内容作为数组获取。然后重新创建文件结构,在目录内有正确的名称、类结构、括号、方法和注释部分的文件准备填写用于 php UnitTest。

    总结一下:给一个目录名称,获取其中所有目录作为键和所有文件作为值的单层数组。

    我进一步扩展了他们的答案,您会得到以下信息:

    function getPathContents($path)
    {
         // was a file path provided?
         if ($path === null){
            // default file paths in codeigniter 3.0
            $dirs = array(
                './models',
                './controllers'
            );
        } else{
            // file path was provided
            // it can be a comma separated list or singular filepath or file
            $dirs = explode(',', $path);
        }
        // final array
        $contents = array();
        // for each directory / file given
        foreach ($dirs as $dir) {
            // is it a directory?
            if (is_dir($dir)) {
                // scan the directory and for each file inside
                foreach (scandir($dir) as $node) {
                    // skip current and parent directory
                    if ($node === '.' || $node === '..') {
                        continue;
                    } else {
                        // check for sub directories
                        if (is_dir($dir . '/' . $node)) {
                            // recursive check for sub directories
                            $recurseArray = getPathContents($dir . '/' . $node);
                            // merge current and recursive results
                            $contents = array_merge($contents, $recurseArray);
                        } else {
                            // it a file, put it in the array if it's extension is '.php'
                            if (substr($node, -4) === '.php') {
                                // don'r remove periods if current or parent directory was input
                                if ($dir === '.' || $dir === '..') {
                                    $contents[$dir][] = $node;
                                } else {
                                    // remove period from directory name 
                                    $contents[str_replace('.', '', $dir)][] = $node;
                                }
                            }
                        }
                    }
                }
            } else {
                // file name was given
                $contents[] = $dir; 
            }
        }
        return $contents;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-08-22
      • 2010-09-30
      • 2016-05-20
      • 1970-01-01
      • 1970-01-01
      • 2018-09-12
      相关资源
      最近更新 更多