thinkphp创建文件夹
ThinkPHP里创建文件夹,创建最直接的文件方式是用PHP原生函数 先看最基础的文件场景。你要在 这段代码在TP里也能用,但 有人会问,TP不是有Filesystem吗?对, 这个方法会自动递归创建,也会处理权限。但它的路径是相对于磁盘根目录的,不是绝对路径。如果你要建的目录不在磁盘根目录下,这招就不灵了。我个人的习惯是:跟上传、缓存、日志相关的目录,走Filesystem;临时目录或者项目外路径,直接用 权限问题绕不开。在Linux上,PHP-FPM的运行用户通常是 还有一个坑:并发创建。两个请求同时判断 这段逻辑来自PHP官方文档的评论区,先尝试创建,失败了再检查目录是否真的不存在。如果确实不存在,才抛异常。这样并发场景下也不会误报。 Windows开发环境另说。Windows对权限不敏感, 最后提一个实际项目里的做法。我们有个内容管理系统,每篇文章的图片按 所以,ThinkPHP创建文件夹这件事,框架给了工具,但别迷信工具。搞清楚路径基准和运行用户,比记住某个方法名重要得多。mkdir(),但框架本身也提供了封装好的创建文件操作类。很多人一上来就写 mkdir($path,文件 0755, true),能跑通,创建但放到TP项目里其实有更稳妥的文件写法。我见过不少项目因为权限和路径问题,创建在Linux服务器上创建目录时直接报错,文件排查半天才发现是创建根路径没走对。public/uploads 下面按日期建目录,创建比如 20250101。文件原生写法是创建这样:$path = './uploads/' . date('Ymd'); if (!is_dir($path)) { mkdir($path, 0755, true); }./ 是文件相对于入口文件的,不是创建相对于项目根目录。如果你在命令行里跑,当前工作目录一变,路径就飘了。所以更推荐用 app()->getRootPath() 或者 root_path() 辅助函数拼绝对路径。use think\facade\Filesystem; $path = root_path('public') . 'uploads/' . date('Ymd'); if (!is_dir($path)) { mkdir($path, 0755, true); }think\facade\Filesystem 底层是League\Flysystem,它确实有 createDir 方法。但注意,它创建的是“磁盘”下的目录,不是任意路径。你得先配置好磁盘根目录,比如在 config/filesystem.php 里把 public 盘指向 public/storage,然后用:Filesystem::disk('public')->createDir('uploads/' . date('Ymd'));mkdir 加 root_path()。www-data 或 nginx,你手动 mkdir 出来的目录属主可能是 root,之后程序再往里写文件就报 Permission denied。解决办法有两个:一是提前把父目录权限设好,比如 chmod -R 775 public/uploads 并且把用户组改成FPM用户组;二是在代码里 mkdir 之后立刻 chmod,但这样每次创建都多一次系统调用,不太优雅。!is_dir($path),都返回true,然后都去 mkdir,第二个就会报“目录已存在”的警告。虽然TP的错误处理会把它变成异常,但你可以用 @mkdir 抑制警告,或者直接判断返回值。更稳的写法是:if (!is_dir($path)) { if (!mkdir($path, 0755, true) && !is_dir($path)) { throw new \RuntimeException(sprintf('目录 "%s" 创建失败', $path)); } }0755 会被忽略,但路径分隔符要注意。TP的 root_path() 返回的路径在Windows下是反斜杠,拼上 /uploads 也能用,PHP会自动处理。不过为了跨平台,建议用 DIRECTORY_SEPARATOR 或者干脆全用正斜杠,PHP在Windows下也认。uploads/article/{ id}/ 存放。创建逻辑写在模型的事件回调里,onAfterInsert 拿到自增ID后建目录。代码不长,但把路径拼接、权限检查、异常捕获都包进了一个私有方法。跑了一年多,没再出现过目录创建失败的问题。