mkdir()递归创建目录必须传第三个参数true,否则多级路径会失败;权限参数0755在容器等环境可能受umask影响,需用chmod补全;is_dir()前须rtrim末尾斜杠以防误判。
PHP 的 mkdir() 默认不支持递归,直接对不存在的父目录调用会失败并报 Warning: mkdir(): No such file or directory。必须显式传入第三个参数 true,否则哪怕路径里有好几层嵌套(比如 logs/2025/06/15),也会卡在第一级就中断。
常见错误写法:mkdir('logs/2025/06/15'); → 失败
正确写法:mkdir('logs/2025/06/15', 0755, true);
0,如 0755)true 表示递归创建所有缺失的上级目录true 仍必须传如果目录可能已存在,直接调用 mkdir() 会触发 Warning: mkdir(): File exists。不要依赖 @mkdir() 抑制错误——它掩盖真实问题,且无法区分“已存在”和“没权限”等不同失败原因。
更稳妥的做法是先检查:
if (!is_dir($path)) {
if (!mkdir($path, 0755, true)) {
throw new RuntimeException("Failed to create directory: $path");
}
}
is_dir() 比 file_exists() 更准确:后者对文件也返回 true,而我们只关心目录mkdir() 返回 false,也不代表完全失败(比如部分路径创建成功),所以检查返回值比单纯看 warning 更可靠PHP 的 is_dir() 对末尾带斜杠的路径(如 'logs/')在某些系统(尤其是 Windows + 某些 PHP 版本)下可能返回 false,即使目录真实存在。这会导致误判、重复创建甚至报错。
解决方法统一用 rtrim($path, '/\\') 去掉末尾斜杠再判断:
$path = rtrim($path, '/\\');
if (!is_dir($path)) {
mkdir($path, 0755, true);
}
/ 和 \)Linux 容器、Docker 或部分共享主机(如 cPanel)会受 umask 限制,即使你传了 0755,实际创建的目录权限可能是 0700 或 0750。这不是 PHP 错误,而是系统级行为。
验证方式:var_dump(substr(sprintf('%o', fileperms($path)), -4)); —— 查看真实权限
chmod($path
, 0755) 强制补全(注意:仅对当前目录有效,不递归)RUN mkdir -p /var/log/app && chmod 755 /var/log/app 预设权限mkdir() 在所有环境都精确还原你传的权限值is_dir() 对末尾斜杠敏感——这些细节不处理,递归建目录看着简单,上线后却常在边缘 case 上出问题。