Composer不支持多环境切换,唯一可靠生产开关是composer install --no-dev;它强制跳过require-dev依赖安装,且不受APP_ENV等变量影响,需在CI或Docker中显式使用。

Composer 本身不支持“多环境切换脚本”这种概念——它没有环境变量感知能力,也不解析 .env 或 APP_ENV 来决定装什么包、用哪个 PHP 版本。所谓“动态同步”,本质是人工控制执行上下文,不是 Composer 自动适配。
composer install --no-dev 是唯一可靠的生产环境开关
你不能靠写个脚本让 Composer “自动识别当前是 dev 还是 prod”,它根本不看环境变量。真正起作用的只有 --no-dev 参数:
- 加了就跳过
require-dev里的所有包(如phpunit/phpunit、laravel/pint),vendor 目录里压根不会出现它们 - 不加就全装,不管
APP_ENV=production还是CI=true,都没用 - 这个参数不影响
autoload-dev的定义,只控制安装行为;但要注意:没装的包,其类也不会被自动加载器注册
COMPOSER_DEV_MODE=0 不推荐,且常失效
有人试过设 COMPOSER_DEV_MODE=0 再跑 composer install,以为能等效于 --no-dev。但实际中它:
- 只在极少数旧版本 Composer 中部分生效,2.2+ 已基本弃用
- 无法绕过
post-install-cmd脚本里对 dev 包的调用(比如php vendor/bin/phpunit会直接报错) - 和
config.platform混用时逻辑混乱,容易导致 lock 文件生成不一致
想“动态同步配置”,必须靠外部脚本封装
真正的动态逻辑得由 shell 或 CI 工具完成,例如 GitHub Actions 中:
if [ "$ENVIRONMENT" = "production" ]; then composer install --no-dev --optimize-autoloader else composer install fi
关键点:
- 别把判断逻辑塞进
composer.json的scripts字段里——那里面只能写固定命令或 PHP 回调,没法读取外部环境变量 - 如果要用
composer run-script做封装,得把环境判断提前到 shell 层,再传参进去,比如:composer run-script deploy -- --env=prod - 所有涉及路径、PHP 版本、扩展依赖的检查(如
ext-pdo、memory_limit),都得在执行composer install前完成,Composer 不会帮你做这些
最易被忽略的是:即使你用脚本控制了 --no-dev,若 composer.lock 是在 dev 环境下生成的,生产部署时仍可能因平台差异(如 PHP 小版本、扩展缺失)触发重新解析,导致意外降级或失败。所以 lock 文件必须和目标环境一致——要么在 CI 中用生产镜像生成,要么用 config.platform 锁定 PHP 版本。


















