必须在脚本多次检查同一文件且该文件可能被外部修改时调用clearstatcache(),否则返回过期缓存结果;典型场景包括logrotate重建日志、chmod后立即检测权限、单元测试中反复touch/unlink;注意对曾存在过的文件,删除后file_exists()仍返回true,需手动清除缓存。

什么时候必须调用 clearstatcache()
当脚本中多次调用 file_exists()、is_file()、filesize() 等函数检查**同一个文件**,且该文件可能在脚本运行期间被外部进程创建、删除或修改时,就必须调用 clearstatcache()。否则 PHP 会返回过期的缓存结果。
典型场景包括:
- 循环监听某个日志文件是否存在并读取(文件可能被 logrotate 删除后重建)
- 上传后立即检查
is_writable(),但权限刚被chmod命令修改过 - 单元测试中反复
touch+unlink同一个测试文件,却始终得到旧的file_exists()结果
注意:file_exists() 对「从未存在过的文件」不缓存,所以第一次返回 false 是可靠的;但一旦该文件被创建过,哪怕之后被删掉,缓存仍会返回 true —— 这就是最常踩的坑。
clearstatcache() 的两种调用方式和影响范围
它支持无参和带参两种调用,行为差异极大:
-
clearstatcache()(无参数):清空**全部**文件状态缓存,影响所有后续对任何文件的stat()类函数调用 -
clearstatcache(true, $filename)(PHP ≥ 5.4.0):只清除指定文件的缓存,第二个参数是路径字符串,比如/tmp/test.txt
推荐优先使用带参数的版本,避免误伤其他正在被检测的文件缓存。尤其在长生命周期的 CLI 脚本或常驻进程中,全局清空可能引发意外性能抖动。
哪些函数受 clearstatcache() 影响
不是所有文件操作函数都走这套缓存机制。只有以下这些会读取文件元数据的函数才被缓存,也才需要 clearstatcache() 来刷新:
-
stat()、lstat()、fstat() -
file_exists()、is_file()、is_dir()、is_link() -
is_readable()、is_writable()、is_executable() -
filemtime()、fileatime()、filectime()、filesize()、fileinode()、fileowner()、filegroup()、filetype()、fileperms()
file_get_contents()、fopen()、rename() 这类实际 I/O 操作函数不受影响,它们不依赖缓存,也不触发缓存写入。
Windows 和 Linux 下的路径注意事项
缓存键基于**完整路径字符串**,大小写和分隔符差异都会导致缓存不命中或重复缓存:
- 在 Windows 上,
C:\temp\test.txt和c:/temp/test.txt被视为两个不同文件,各自有独立缓存 - Linux 下路径严格区分大小写,
/tmp/TEST.TXT和/tmp/test.txt缓存分离 - 符号链接目标文件的状态缓存,与链接本身路径无关 ——
stat()总是缓存目标,不是链接路径
因此,调用 clearstatcache(true, $path) 时,传入的 $path 必须和之前调用 file_exists() 等函数时用的完全一致,否则清不掉。
最易忽略的一点:缓存是 per-request / per-process 的,Web SAPI(如 Apache mod_php 或 FPM)里每个请求都是独立进程或线程,缓存不会跨请求残留;但在 CLI 持久化脚本、Swoole Worker 或某些常驻协程环境中,缓存可能持续数秒甚至更久,这时漏掉 clearstatcache() 就会卡在“明明删了文件,file_exists() 还返回 true”的状态里。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











