mkdir()递归创建多级目录必须显式传第三个参数true,否则因父目录不存在而报错;权限需用八进制字面量(如0755),且受umask影响,必要时应配合chmod()补设。

mkdir 递归创建多级目录必须传 true
PHP 的 mkdir() 默认不建父目录,哪怕路径是 /a/b/c,只要 /a/b 不存在,就会直接报 Warning: mkdir(): No such file or directory。这不是路径写错了,是函数行为本身如此。
解决方法只有一个:第三个参数必须显式设为 true。
-
mkdir('/tmp/foo/bar', 0755, true)—— 成功,自动建/tmp/foo再建bar -
mkdir('/tmp/foo/bar', 0755)或mkdir('/tmp/foo/bar', 0755, false)—— 失败,除非/tmp/foo已存在 - 别依赖默认值,
false是默认,但几乎没人真想要它
权限数字必须写成八进制字面量(开头带 0)
0755 和 755 在 PHP 里完全不是一回事:0755 是八进制,表示 rwxr-xr-x;755 是十进制,等于八进制 1363,权限位混乱,实际效果不可控。
常见错误现象:mkdir('log', 755, true) 看似正常返回 true,但目录权限可能是 drw-r--r-- 或其他异常组合,后续写入失败。
- 永远用
0755、0700、0644这类带前导0的写法 - Web 可读目录推荐
0755;仅限当前用户访问的缓存或配置目录用0700 - 别用
0777,哪怕临时调试也不建议——它绕过组权限控制,容易被滥用
umask 会吃掉你指定的权限
即使写了 mkdir($path, 0777, true),Linux 下实际权限往往仍是 0755。这是因为 PHP 创建目录时会把 $mode 和系统 umask 做按位与取反运算(mode & ~umask)。默认 umask 通常是 0022,所以 0777 & ~0022 = 0755。
两种靠谱应对方式:
- 先调
umask(0),再mkdir(),完事再恢复原 umask(需保存旧值) - 更推荐:先
mkdir($path, 0755, true),再立刻chmod($path, 0777)——chmod()不受 umask 影响,能精确落地 - 注意:
chmod()必须在mkdir()成功后调用,且目标必须是已存在的目录
Windows 下路径长度和权限逻辑完全不同
Windows 不解析 0755 这类 Unix 权限,mkdir() 的 $mode 参数会被忽略。但它有自己的一套限制:
- 路径总长不能超过 260 字符(MAX_PATH),否则报
No such file or directory—— 即使路径语法完全正确 - 长路径需启用 NTFS 的
\?前缀,但 PHP 的mkdir()不支持该前缀,只能靠缩短路径或改用绝对路径规避 - 权限由 Windows ACL 控制,PHP 无法通过
mkdir()或chmod()修改,得靠cacls或 PowerShell 脚本 - 跨驱动器路径(如
D:logspp)比相对路径更稳定,尤其在 CLI 模式下
真正麻烦的从来不是调用 mkdir() 这一行代码,而是它背后那三层隐性约束:递归开关、八进制字面量、umask 干扰。漏掉任意一个,目录就可能“看似建成了”,实则不可写、不可读、或根本没建全。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











