PHP 7.4目录树生成器的核心难点是路径拼接、引用陷阱、错误隔离和资源释放;典型空子目录问题源于数组值传递导致递归修改不可见,须用return构建完整子树并统一用DIRECTORY_SEPARATOR拼接路径。

PHP 7.4 下手动实现目录树生成器,核心难点不在递归逻辑本身,而在于**路径拼接、引用陷阱、错误隔离和资源释放**——用 scandir + is_dir 能跑通,但一上线就报错或漏子目录,多半栽在这几处。
为什么 scandir + 递归常返回空子目录
典型现象:顶层目录能列出来,但每个子目录对应的键值是空数组 [],不是嵌套结构。
- 根本原因是把子数组当引用传入递归调用,比如
$result[$entry] = []后传$result[$entry]给下一层,但 PHP 数组默认按值传递,递归内部改了它,上层没感知 -
opendir/readdir方式若没配closedir,句柄泄漏可能让后续迭代失败,但错误不显式抛出,只静默跳过 -
scandir返回结果含.和..,没过滤会导致is_dir($path . '/.') === true,无限递归进当前目录
getFiles() 必须返回数组,不能靠引用修改外部变量
正确模式是函数始终 return 一个完整子树,由调用方决定怎么存 —— 这是 PHP 7.4+ 引用语义收紧后最安全的做法。
- 入口函数里不要写
getFiles($path, &$tree),改用$tree = getFiles($path) - 递归体中,对每个子目录调用
$children = $this->getFiles($fullPath),再赋值给$entries[$entry]['children'] = $children(如果是目录)或直接 push 到文件列表 - 避免在递归函数里做
echo或print_r,PHP 7.4 的输出缓冲行为更严格,容易中断 JSON 输出或 HTTP 响应
路径拼接必须用 DIRECTORY_SEPARATOR,别硬写 / 或 \
Windows 下 scandir('C:\foo') 可能成功,但 'C:\foo\bar' 拼接时反斜杠被当转义符,is_dir 判定失败。
立即学习“PHP免费学习笔记(深入)”;
- 统一用
$fullPath = $directory . DIRECTORY_SEPARATOR . $item - 检查前先
realpath($fullPath),可提前暴露符号链接循环或权限不足问题 - 对
is_readable($fullPath) === false的项直接跳过,不尝试is_dir,否则非读取权限目录会触发 warning
实际部署时最容易被忽略的三件事
本地跑得通,放到生产环境就卡住或超时,往往不是算法问题,而是运行时约束没处理:
- PHP
max_execution_time默认 30 秒,深目录树可能超时,需临时设set_time_limit(120)(注意 CLI 和 Web SAPI 行为差异) - 递归深度过大(如 >100 层)可能触达 PHP 栈限制,加个深度计数参数,在递归调用前判断
if ($depth > 10) return []; - 没过滤
.git、.env、vendor/等敏感或大体积目录,既拖慢速度,又可能暴露配置文件路径



















