composer install 默认只安装 production 依赖,即仅读取 composer.lock 中的 require 包,跳过 require-dev;需显式加 --dev 参数才安装测试依赖,否则导致 phpunit 等类找不到。

composer install 默认只装 production 依赖
执行 composer install 时,它会读取 composer.lock 并仅安装 "require" 中的包,跳过 "require-dev" 里的内容——这是默认行为,不是 bug,是设计如此。
常见错误现象:phpunit 找不到、mockery 报 Class not found,但 composer.json 里明明写了;其实只是没装进去。
- 确认当前环境:运行
composer install --no-dev(显式禁用 dev)和composer install(默认也是 --no-dev)效果一样 - 想装测试依赖?必须加
--dev或-d参数:composer install --dev - CI/CD 流水线里漏掉
--dev,会导致测试跑不起来,但本地开发可能因缓存“碰巧”能过
composer update 的 dev 模式要主动指定
composer update 默认行为和 install 一致:只更新 require,忽略 require-dev。很多人以为“update 就是全量刷新”,结果改了 phpunit 版本却没生效。
使用场景:升级测试工具链、同步团队 dev 依赖版本、修复 dev 包的安全告警。
- 更新全部(含 dev):
composer update --dev - 只更新某个 dev 包:
composer update --dev phpunit/phpunit - 注意:如果 lock 文件里没有 dev 包记录,
--dev会按composer.json重新解析并写入 lock,可能触发意外升级
如何让生产部署彻底不带测试依赖
光靠 --no-dev 不够稳。有些包在 require-dev 里声明了 autoloader,但实际代码被主逻辑引用,上线后报 Class not found——这说明开发时没隔离干净。
围绕关键发现、作用机制、临床相关性及研究局限性展开讨论。适用于撰写或优化任何生物医学论文的“讨论(Discussion)”部分——包括结果解读、与既往文献关联、阐释意外发现、界定研究局限性,以及撰写结论。当用户输入以下任一指令时也会自动触发该功能: - “write my discussion” - “help me discuss my findings” - “how do I compare to prior studies” - “write the limitations par
性能与兼容性影响:dev 包通常不参与运行时,但若 autoloader 注册了全局 PSR-4 映射,可能拖慢类加载、增加内存占用,甚至引发命名冲突。
- 上线前务必用
composer install --no-dev --optimize-autoloader --classmap-authoritative -
--classmap-authoritative是关键:它让 autoloader 完全信任 classmap,不回退到文件扫描,能暴露那些“只在 dev autoloader 里注册、实际却在生产代码中 new 出来的类” - 检查
vendor/autoload.php是否被修改过(比如手动追加了 dev 路径),这种 hack 在 --no-dev 下直接失效
环境变量 COMPOSER_DEV_MODE 不起作用
有人尝试设 COMPOSER_DEV_MODE=0 或 1 来控制行为,但 composer 从 v2 开始已移除该变量支持——它现在只认命令行参数,不读环境变量。
容易踩的坑:Dockerfile 里写 ENV COMPOSER_DEV_MODE=0,以为能锁定生产模式,结果毫无效果。
- 正确做法:在部署命令中明确写死
--no-dev,不要依赖环境变量 - CI 脚本里避免用
if [ "$CI_ENV" = "prod" ]; then composer install; else composer install --dev; fi这类逻辑——应统一用参数驱动,而非分支判断 - composer config 命令也不能设置全局 dev 模式,
composer config --global不影响 install/update 的依赖范围
真正难处理的是那种“部分 dev 包需要进生产”的情况,比如 symfony/debug 用于开发调试,但某些错误页组件又依赖它——这时候得拆包或用 replace + 自定义 autoloader,而不是指望 composer 自动区分。

















