生产环境应使用 composer install --no-dev --optimize-autoloader --classmap-authoritative,它校验 lock、跳过 dev 包、生成权威 classmap 并禁用 psr-4 回退;需清理框架缓存并验证 autoload_classmap.php 和 stat 调用。

生产环境别单独跑 composer dump-autoload -o
它大概率白干。Composer 2.x 默认已启用 classmap 生成逻辑,dump-autoload -o 不再触发完整 classmap 扫描,除非项目里明确定义了 "classmap" 字段或存在兼容性 fallback。真正生效的命令是:composer install --no-dev --optimize-autoloader。这个命令会:校验 composer.lock、跳过 require-dev 包、强制重生成 autoload_classmap.php、并启用优化模式——三件事一步到位。
--classmap-authoritative 不是可选项,是生产环境必须项
只加 -o 还不够。不加 --classmap-authoritative(或简写 -a),Composer 仍会在 classmap 查不到时 fallback 到 PSR-4 路径猜测,反而多一次文件系统 stat() 调用,可能更慢。加上后,它才真正“只信这张表”,彻底绕过目录遍历。但注意:这要求所有运行时用到的类都必须被扫描进 classmap,否则直接报 Class not found。
- 动态拼类名(如
$class = $prefix . 'Handler')不会进 classmap,得提前require_once或改用class_alias() - Laravel 的路由闭包、Symfony 的服务配置里匿名类,若未显式声明在
classmap或 PSR-4 规则下,也会挂掉 - 测试类、Mock 类、AOP 织入代码必须从 autoload 配置中剔除,否则 classmap 会膨胀且失效
验证是否真生效,别只看命令有没有报错
执行完部署命令后,立刻检查两个地方:
- 打开
vendor/composer/autoload_classmap.php,搜你项目的主命名空间(比如App\),确认路径已写死为绝对路径数组,而非空数组或只有 vendor 包的条目 - 用
strace -e trace=stat php -r "new AppModelsPost();"看是否还有大量stat("/path/to/src/Models/Post.php")失败调用;没有,说明 fallback 已关闭 - 如果用了 opcache,还要确认
opcache.preload没和 classmap 冲突——preload 文件里不能有class_exists()或new,否则 FPM 启动失败
CI/CD 流程里最容易漏掉的一环
很多人把 composer install --no-dev --optimize-autoloader 写进部署脚本,却忘了清理旧缓存。Laravel 的 php artisan config:clear、php artisan view:clear 必须跟在后面执行,否则框架可能还在用旧的已编译视图或配置缓存,导致新类看似“加载失败”。这不是 autoload 问题,而是缓存层遮蔽了真实状态。











