opcache 修改php文件未生效是因为其默认缓存字节码且不实时校验源文件变更;开发环境应设opcache.validate_timestamps=1并调低opcache.revalidate_freq,生产环境推荐reload php-fpm而非opcache_reset()。
OPcache 缓存为什么改了 PHP 文件却没生效
因为 OPcache 默认把编译后的字节码常驻内存,不检查源文件是否变更。哪怕你 touch 了文件、重启了 Web 服务(如 Apache),只要 OPcache 没被清空或重载,旧字节码就还在跑。
常见现象包括:修改了 index.php 但页面输出仍是旧逻辑;var_dump(__FILE__) 显示路径正确,但内容未更新;用 opcache_get_status() 查看发现 opcache.hit_rate 很高,但 opcache.files_count 和实际文件数对不上。
-
开发环境建议关闭
opcache.validate_timestamps(设为1),否则它只在每次请求时按固定间隔(默认 2 秒)检查一次时间戳,不是实时的 -
opcache.revalidate_freq值越大,延迟越明显;设为0才真正“每次请求都校验”,但会牺牲性能 - 某些 Docker 或容器化部署中,宿主机改文件、容器内 PHP 进程可能因挂载方式看不到 mtime 变更,导致 validate 失效
手动刷新 OPcache 的三种可靠方式
不是所有方式都“即时”——关键看是否触发了字节码重编译,以及是否影响全部 worker 进程。
- 调用
opcache_reset():必须在脚本中执行,且该脚本本身不能被 OPcache 缓存(否则函数根本不会运行)。推荐放在独立的opcache-reset.php中,并确保该文件不在opcache.blacklist_filename里,访问一次即重置全站缓存 - 调用
opcache_invalidate($script, $force):只清指定文件,$force = true才跳过时间戳校验强制重载。注意路径必须是绝对路径(可用realpath(__FILE__)获取) - 重启 PHP-FPM 进程:
sudo systemctl reload php*-fpm或kill -USR2 $(cat /var/run/php/php*-fpm.pid)。这是最彻底的方式,但会造成短暂请求失败(取决于进程管理策略)
别用 opcache_compile_file() 单独预热——它不触发自动依赖解析,require 的其他文件仍可能走旧缓存。