You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PHP使用RecursiveDirectoryIterator遍历目录如何按字母排序保留层级结构

问题根源

你现在遇到directories字段为空的核心原因是RecursiveIteratorIterator默认使用RecursiveIteratorIterator::LEAVES_ONLY遍历模式,只会返回文件(叶子节点),不会返回目录节点,所以$file->isDir()的判断永远不会命中。

实现方案

不需要更换迭代器,只需要调整遍历模式、调整数组结构拼装逻辑,最后做轻量排序即可,完全可以保留原有迭代器的性能优势,修改后的代码如下:

function get_directory_contents($directory, $hide_index_files = TRUE, $limit_to_html_files = TRUE) {
    // 调整遍历模式为SELF_FIRST,会先返回目录节点,再返回其下内容
    $rdi = new RecursiveDirectoryIterator($directory, RecursiveDirectoryIterator::SKIP_DOTS);
    $rii = new RecursiveIteratorIterator($rdi, RecursiveIteratorIterator::SELF_FIRST);
    $result = ['files' => []];
    $rootPathLength = strlen(rtrim($directory, '/') . '/');

    foreach ($rii as $file) {
        // 先处理目录:提前初始化到结果数组,支持空目录展示
        if ($file->isDir()) {
            $relativePath = substr($file->getPathname(), $rootPathLength);
            // 中文/特殊文件名兼容转码可选,不需要可以删掉
            $relativePath = mb_convert_encoding($relativePath, 'UTF-8', 'GBK,UTF-8');
            if (!isset($result['files'][$relativePath])) {
                $result['files'][$relativePath] = [];
            }
            continue;
        }

        // 过滤规则和原有逻辑一致
        $filename = $file->getFilename();
        if ($hide_index_files && $filename === 'index.html') {
            continue;
        }
        if ($limit_to_html_files && substr($filename, -5) !== '.html') {
            continue;
        }

        // 拼装路径
        $fullRelativePath = substr($file->getPathname(), $rootPathLength);
        $dirRelativePath = substr($fullRelativePath, 0, -strlen($filename) - 1);
        // 根目录文件归到base_directory
        $dirKey = $dirRelativePath ?: 'base_directory';

        // 把文件放到对应目录分组下
        $result['files'][$dirKey][] = [
            'fullpath' => $fullRelativePath,
            'filename' => $filename
        ];
    }

    // 按字母序排序目录名
    ksort($result['files'], SORT_NATURAL | SORT_FLAG_CASE);
    // 每个目录下的文件也按字母序排序
    foreach ($result['files'] as &$fileList) {
        usort($fileList, function($a, $b) {
            return strnatcasecmp($a['filename'], $b['filename']);
        });
    }
    unset($fileList); // 解除引用

    return $result;
}

关键修改说明

  • 遍历模式改为RecursiveIteratorIterator::SELF_FIRST,即可获取所有目录节点,空目录也会被提前初始化到结果数组中,解决空文件夹不展示的问题
  • 直接按目录相对路径作为数组键存储对应文件列表,天然保留目录结构
  • 最后使用ksort对目录名做自然排序(不区分大小写),每个目录下的文件用usort做文件名自然排序,排序操作仅在内存中对结构化数组执行,几乎不会增加性能开销
  • 原有文件过滤逻辑完全保留,符合你的业务需求

输出说明

返回的数组结构完全符合你的预期,你可以直接用这个结构渲染目录树,根目录的base_directory对应你要展示的/根路径。

内容的提问来源于stack exchange,提问作者Kaboom

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.12 08:57:03