PHP mkdir() 默认仅创建单层目录,多级路径必须显式传入第三个参数 true 启用递归模式,否则因父目录缺失而失败;Windows 下 mode 参数无效,中文路径需 iconv 转 GBK;创建前应先用 is_dir() 判断避免误报。

PHP mkdir() 默认只能创建单层目录,多级路径必须显式启用 recursive 参数,否则直接失败 —— 这是绝大多数人踩坑的起点。
mkdir 创建多级目录必须传 true 给第三个参数
很多人写 mkdir("a/b/c") 发现报错或静默失败,原因就是没开递归。PHP 5.0.0+ 才支持该参数,且必须明确传 true,不能省略或传 1(虽然类型转换后可能凑巧生效,但语义不清)。
-
mkdir("logs/2026/08/31", 0755, true)✅ 正确:逐级创建所有不存在的父目录 -
mkdir("logs/2026/08/31", 0755)❌ 失败:只要logs或logs/2026任一上级不存在,就返回false -
mkdir("logs/2026/08/31", 0755, 1)⚠️ 不推荐:布尔值应写true,避免类型混淆
权限 mode 在 Windows 下完全无效
Windows 系统不支持 Unix 权限模型,mode 参数会被直接忽略。你在 Windows 上传 0777 或 0644,创建出来的目录权限都由系统策略和父目录继承决定,跟参数无关。
- Linux/macOS:
0755表示所有者可读写执行,组和其他人仅读+执行;注意实际生效权限还受当前umask影响(比如umask(0022)会让0777变成0755) - Windows:放心传任意八进制数,它不会报错,但也不会起作用
- 跨平台项目建议统一用
0755,既满足 Linux 安全要求,又在 Windows 下无副作用
中文路径要先转码,否则在 Windows 上大概率失败
PHP 内部字符串默认按字节处理,而 Windows 文件系统 API 要求 GBK 编码的路径。UTF-8 路径直接传给 mkdir() 会导致乱码、找不到父目录或创建空名目录。
立即学习“PHP免费学习笔记(深入)”;
- 正确做法:
mkdir(iconv("UTF-8", "GBK", $path), 0755, true) - 注意:只在 Windows 环境下需要转码;Linux/macOS 原生支持 UTF-8 路径,转码反而出错
- 更稳妥的方式是判断环境:
PHP_OS_FAMILY === 'Windows'再决定是否调用iconv
mkdir 返回 false 不代表“没干任何事”,得先检查目录是否存在
mkdir() 遇到已存在目录时返回 false,并触发 E_WARNING,但目录本身没被破坏。如果逻辑里没做前置判断,容易误判为“创建失败”而重复尝试或抛异常。
- 安全写法总是配
is_dir($path)或file_exists($path): if (!is_dir($path) && !mkdir($path, 0755, true)) { /* 真正的错误处理 */ }- 注意:
file_exists()比is_dir()更宽泛(能捕获符号链接等),但若确定只关心目录,用is_dir()语义更准
真正麻烦的是权限叠加、umask 干扰、网络文件系统挂载点限制这些隐性因素 —— 它们不会让 mkdir() 报明显错误,但会导致后续 fopen() 或 file_put_contents() 失败。调试时别只盯函数返回值,得用 ls -ld(Linux)或属性查看(Windows)确认最终权限和归属。



















