composer dump-autoload --apcu 不保证 apcu 缓存生效,因 cli 默认 apc.enable_cli=0 导致 apcu_store() 静默失败;需手动验证 cli 环境配置及写入能力,并确保 fpm 进程独立启用 apcu、重启或清缓存以使 web 请求命中。

composer dump-autoload --apcu 不是加参数就生效
这个命令本身不校验 APCu 是否可用,只尝试调用 apcu_store()。一旦 PHP CLI 模式下 apc.enable_cli=0(默认值),apcu_store() 就会静默返回 false,缓存根本没写进去,但命令仍显示成功。你看到的只是生成了 autoload_static.php,不是“APCu 缓存已就位”。
必须手动验证 CLI 环境是否真能写入:
- 运行
php -i | grep "Loaded Configuration File",确认 CLI 实际加载的php.ini路径 - 检查该文件中是否同时存在:
extension=apcu.so(或.dll)、apc.enabled=1、apc.enable_cli=1 - 执行
php -r "var_dump(apcu_store('test', 'ok'));",输出bool(false)就说明 CLI 下 APCu 写入已失效
--apcu 只缓存类名→路径映射,且依赖 classmap
--apcu 并不加速文件加载本身,也不跳过 require 或影响 OPcache。它干的事非常窄:把 App\Http\Controllers\HomeController → /var/www/src/Http/Controllers/HomeController.php 这种映射关系存进 APCu 内存,key 形如 composer-apcu-autoloader- + hash。
但它有个硬前提:项目必须已生成 classmap。否则缓存无数据可存。
- 没开
"optimize-autoloader": true或没跑过composer dump-autoload -o,autoload_classmap.php为空或极简,--apcu几乎无效 - 只对 PSR-4/PSR-0 映射生效;
classmap方式本身已是静态数组,无需 APCu 加速 -
"files"类型自动加载(如全局 helper)不会进 APCu 缓存,靠 OPcache 处理
CLI 生成 ≠ Web 端可用,FPM 才是真正读缓存的地方
CLI 下执行 composer dump-autoload --apcu,缓存只存在于当前进程生命周期内 —— 它写进了 CLI 进程的 APCu 上下文,而 PHP-FPM worker 进程有自己独立的 APCu 实例(哪怕共享同一块 shm)。Web 请求根本读不到 CLI 写的缓存。
所以部署时不能只在构建阶段跑这一条命令:
- 必须确保 FPM 进程启动时 APCu 已就绪(
apc.enabled=1且apc.enable_cli=1不影响 FPM) - 每次更新 vendor 后,要重启 PHP-FPM 进程,或在代码里调用
apcu_clear_cache('user')清旧缓存 - 验证是否真命中:运行
php -r "print_r(apcu_cache_info('user'));",找 key 含composer-apcu-autoloader-的条目
生产部署别单独用 dump-autoload --apcu
它只刷新 PSR 映射逻辑,不重建 classmap,也不清旧缓存。在 CI/CD 流水线里直接用,极易导致缓存错乱或 Class not found 错误。
正确做法是统一走 composer install 流程:
- 部署命令应为:
composer install --no-dev --optimize-autoloader --classmap-authoritative --apcu-autoloader - 注意参数名:
--apcu-autoloader(两个短横线),不是--apcu;后者仅对dump-autoload子命令有效 -
--classmap-authoritative配合--apcu-autoloader是关键组合:前者让查找完全信任 classmap,后者把未命中的 PSR 查找结果缓存进 APCu,兼顾速度与兜底
APCu 缓存不是持久化存储,它依赖共享内存和进程生命周期。最容易被忽略的是:缓存键基于类名哈希生成,一旦 composer.json 中 autoload 规则变更,旧缓存不会自动失效,必须人工干预清理或重启 FPM。











