在PHP中创建文件夹(如果不存在):2025年最佳实践

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

«Create a folder if it doesn't already exist»:如何在2025年避免重复造轮子

\n\n

您是否曾经编写过需要保存文件的脚本,却突然遇到错误 Warning: mkdir(): No such file or directory?如果是,您并不孤单。关于 «Create a folder if it doesn't already exist» 的问题在 Stack Overflow 上获得了数千次浏览,这并非没有原因。看起来很简单,对吧?但在实践中,新手(甚至老手)常常会陷入陷阱:权限问题、递归创建、竞态条件。

\n\n

在本文中,我们将分析 2025年PHP创建文件夹的最佳实践。您将学习如何正确使用 mkdir(),避免常见错误,并编写在关键时刻不会崩溃的可靠代码。开始吧!

\n\n

为什么«Create a folder if it doesn't exist»问题如此受欢迎?

\n\n

几乎每两个Web项目中就有一个会以某种方式处理文件:上传头像、生成报告、缓存、日志。在任何情况下,都需要确保目标目录存在。如果目录不存在,脚本会报错,用户会看到“500 Internal Server Error”,而您则需要在凌晨三点排查错误。

\n\n

问题在于,PHP函数 mkdir() 不会自动创建父目录。许多开发者会写出类似这样的代码:

\n\n
if (!file_exists($path)) {\n    mkdir($path);\n}\n
\n\n

这确实有效……直到发生 race condition(竞态条件)。如果两个脚本同时检查目录是否存在,并都尝试创建它——其中一个会因错误而崩溃。在2025年,随着网站负载的增加,这类错误变得至关重要。

\n\n

PHP中的 mkdir() 函数:全面解析

\n\n

让我们回顾一下函数签名:

\n\n
mkdir(string $directory, int $permissions = 0777, bool $recursive = false, resource $context = ?): bool\n
\n\n
    \n
  • $directory — 要创建的目录路径。
  • \n
  • $permissions — 权限(默认0777,但受umask影响)。
  • \n
  • $recursive — 如果为 true,则递归创建所有缺失的父目录。
  • \n
  • $context — 流上下文(很少使用)。
  • \n
\n\n

关键秘密在于 $recursive 参数。大多数问题都可以通过它解决。但让我们一步步来。

\n\n

简单方法:is_dir() + mkdir()

\n\n

检查目录是否存在的最明显且正确的方法是使用 is_dir(),而不是 file_exists()。为什么?因为 file_exists() 对于同名文件也会返回 true,从而导致错误。

\n\n
$dir = '/path/to/upload';\n\nif (!is_dir($dir)) {\n    mkdir($dir, 0755, true);\n}\n
\n\n

这里我们:

\n
    \n
  • 检查目录不存在且不是文件。
  • \n
  • 以权限0755创建目录(所有者拥有全部权限,其他人可读可执行)。
  • \n
  • 使用 true 进行递归创建——如果父目录 /path/to 不存在,它也会被创建。
  • \n
\n\n

这种方法覆盖了90%的情况。但如果两个请求同时执行这段代码呢?

\n\n

防止竞态条件(race condition)

\n\n

在高负载系统中,两个脚本可能同时尝试创建目录。为了避免错误,可以使用 @(抑制错误),或者更好的方法是检查 mkdir() 的结果:

\n\n
$dir = '/path/to/cache';\n\nif (!is_dir($dir)) {\n    // 尝试创建。如果另一个进程已经创建了目录,也没关系\n    if (!mkdir($dir, 0755, true) && !is_dir($dir)) {\n        throw new \\RuntimeException('无法创建目录:' . $dir);\n                

博客

书籍推荐