最常见原因是opcache缓存了旧的autoload_static.php或类映射,且php-fpm进程复用时不会因composer dump-autoload自动刷新;需检查opcache配置、清空缓存或重启php-fpm,并确保autoload_static.php中路径正确。

autoload.php 被包含但类仍报 class not found
最常见原因不是自动加载没配,而是 opcache 缓存了旧的类映射或已失效的 autoload_static.php。PHP-FPM 进程复用时,opcache 不会因 composer dump-autoload 自动刷新。
- 确认是否启用了
opcache.enable=1和opcache.enable_cli=0(CLI 下关着不影响,但 web 请求走的是 FPM) - 检查
opcache.revalidate_freq是否设得过大(比如 60 秒),导致修改后等很久才重载 -
composer dump-autoload --optimize会生成vendor/composer/autoload_static.php,这个文件被 opcache 缓存后,删类、改命名空间也不会触发更新
如何让 nginx+PHP-FPM 立即看到 autoload 变更
不能只 reload nginx,必须让 PHP-FPM 进程丢弃 opcache 中的自动加载相关条目,或直接重启进程。
- 最快验证方式:在 PHP 脚本开头加
opcache_invalidate('vendor/composer/autoload_static.php', true)(仅开发环境) - 更稳妥的做法是清空整个 opcache:
opcache_reset(),但需确保该函数未被禁用(检查disable_functions) - 如果权限受限或线上环境不允许调用
opcache_reset(),就只能重启 PHP-FPM:sudo systemctl restart php-fpm或sudo service php7.4-fpm restart(版本按实际改) - Nginx 本身不缓存 autoload,但若配了 FastCGI cache,也要注意
fastcgi_cache_bypass是否绕过了 PHP 执行
验证 autoload 是否生效的最小闭环
别依赖浏览器刷新看错误,用 CLI 和 FPM 各跑一次,对比结果才能定位是 autoload 问题还是 opcache 问题。
- CLI 下执行:
php -d opcache.enable=0 -r "require 'vendor/autoload.php'; var_dump(class_exists('YourNamespaceClass'));"—— 这绕过 opcache,能确认 composer 配置本身对不对 - FPM 下写个
test.php放到 webroot:<?php opcache_get_status()['scripts']['/path/to/test.php'] ?? print_r('opcache not enabled'); var_dump(class_exists('YourNamespaceClass')); ?> - 观察
opcache_get_status()返回中scripts键里有没有你的autoload_static.php路径;如果有且timestamp没更新,说明它被卡住了
autoload_static.php 权限和路径硬编码带来的坑
composer dump-autoload --optimize 生成的静态加载器会把绝对路径写死进 autoload_static.php,一旦项目移动或部署路径不同,FPM 加载时就会静默失败(不报错,只是类找不到)。
立即学习“PHP免费学习笔记(深入)”;
- 检查生成的
vendor/composer/autoload_static.php,搜索__DIR__ . '/—— 如果后面跟的是完整绝对路径(如/var/www/app/vendor/...),说明生成时工作目录不对 - 正确做法是在项目根目录下运行
composer dump-autoload --optimize,确保__DIR__指向vendor/composer/ - CI/CD 部署时若用临时路径构建,务必在最终目标路径下再执行一次
dump-autoload,否则静态加载器指向的是构建机路径
autoload 的问题往往藏在 opcache 和路径两个地方,一个没清干净,一个写错了位置,都只会显示“Class not found”,而不会告诉你哪一步断了。