ThinkPHP删除文件需“先确认、再执行、留痕迹”:数据库用软删除,服务器文件删前校验路径、存在性、权限,删目录需递归清空,批量删除须加开关、日志和限流。

ThinkPHP 中删除文件要防误操作,核心是“先确认、再执行、留痕迹”。不能直接删,得加校验、分场景、做隔离。
删数据库记录:必须用模型软删除
物理删除(Db::name('user')->delete(1))不可逆,极易误删。正确做法是启用软删除:
- 模型中引入
use think\model\concern\SoftDelete;并声明use SoftDelete; - 数据表加
delete_time字段,类型为DATETIME NULL,禁用默认值 - 删操作只走模型:
User::find(1)->delete()或User::destroy(1) - 这样删的是逻辑标记,数据还在,随时可查
User::onlyTrashed()->find(1)->restore()恢复
删服务器文件:路径+存在性+权限三重检查
上传的图片、视频等文件,不能裸调 unlink()。每删一个都必须确认:
- 用
realpath($path)解析并校验路径是否落在允许目录内(防../../etc/passwd遍历) - 用
file_exists($path)确认文件真实存在 - 用
is_writable($path)确认有写权限(注意:对文件是改写权限,对目录是创建/删除权限) - 删完检查返回值:
if (unlink($path) === false) { log_error(...); },不靠 @ 抑制警告
删整个上传目录:先清空再删目录
删文件夹不能直接 rmdir(),它只接受空目录。安全流程是:
立即学习“PHP免费学习笔记(深入)”;
- 用
scandir($dir)或glob($dir . '/*')获取全部子项 - 过滤掉
.和..,逐个判断是文件还是子目录 - 文件用
unlink(),子目录递归清空后再rmdir() - 最后才删父目录,且确保该目录不是公共可访问路径(如不能在
public/uploads下)
批量删或定时清理:加开关和日志
自动任务删文件(如清理过期上传)更需谨慎:
- 配置开关控制是否真正执行删除,开发环境默认关
- 每条删除操作前记录日志:谁删的、删了什么、时间、IP(如果是接口触发)
- 大数量时分批处理,避免超时;每次删完
sleep(0.1)减轻 I/O 压力 - 关键目录加“防护文件”,比如在
runtime/uploads下放一个.keep,脚本遇到就跳过该目录



















