tempnam() 必须传入真实可写目录路径和文件名前缀两个必需参数,返回已创建但权限受限的空文件路径;推荐优先使用更安全的 tmpfile()。

tempnam() 必须传两个参数,缺一不可
tempnam() 不是可选参数函数,dir 和 prefix 都是必需的。漏掉任意一个会触发警告并返回 false。
常见错误写法:tempnam('/tmp') 或 tempnam(null, 'log') —— 这两种都会失败。
-
dir必须是字符串,且指向一个**真实存在、PHP 进程有写权限**的目录;硬编码/tmp在 Windows 或容器里大概率失效 -
prefix仅用于生成文件名开头,Windows 下只取前 3 字符,Linux/macOS 最多用前 63 字符;不要依赖长前缀保证唯一性 - 安全起见,始终用
sys_get_temp_dir()替代手写路径,例如:tempnam(sys_get_temp_dir(), 'cfg_')
tempnam() 返回的是路径,不是文件
它只确保返回的路径“当前不存在”,并**立即创建一个空文件**(自 PHP 4.0.3 起),但这个文件是空的、不可读的,直到你用 fopen() 或 file_put_contents() 写入内容。
典型翻车现场:file_get_contents(tempnam(...)) 直接报 failed to open stream: No such file or directory —— 因为虽然文件已创建,但默认权限是 0600(仅属主可读写),而 file_get_contents() 是读操作,需显式打开再读。
- 正确流程:先
$path = tempnam(...)→ 再file_put_contents($path, $data)→ 最后file_get_contents($path) - 如果只是临时写+读,直接用
tmpfile()更省心,它返回可读写的资源句柄,不用操心路径 - 记得手动
unlink($path)清理,否则文件会一直残留
跨环境时 sys_get_temp_dir() 也不完全可靠
sys_get_temp_dir() 看似万能,但在某些系统上行为受限:
- systemd 的
PrivateTmp=true(如 CentOS 7+ 默认)会让它固定返回/tmp,实际路径却是动态的长路径,导致tempnam()创建失败却无明确报错 - Docker 容器若未挂载
/tmp或限制写入,tempnam()可能静默回退到系统目录,而该目录在容器内根本不可写 - 共享主机可能屏蔽
upload_tmp_dir或TMP环境变量,使sys_get_temp_dir()返回不可用路径
建议加一层校验:if (!is_writable($dir = sys_get_temp_dir())) { throw new RuntimeException("Temp dir {$dir} not writable"); }
tmpfile() 是更安全的替代方案
如果你不需要文件路径(比如不打算传给外部命令、不需用 curl -F 上传),tmpfile() 几乎总是比 tempnam() 更合适:
- 零参数调用:
$fp = tmpfile(),无需担心目录权限或路径拼接 - 自动清理:脚本结束或
fclose($fp)后文件立即删除,无残留风险 - 无法被外部进程访问(
stream_get_meta_data($fp)['uri']在部分环境下为空或不可靠),适合敏感中间数据 - 不支持获取文件路径,所以不能用于需要磁盘路径的场景(如
exec("convert {$path} ..."))
真正难处理的,是既要路径又要自动清理——这种需求得自己封装:用 tempnam() 生成路径 + register_shutdown_function('unlink', $path) 补救,但注意异常中断时仍可能遗漏。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











