composer.json 不支持环境判断,应通过 composer_dev_mode 控制 require-dev、在 php 运行时读取 app_env 分支逻辑,并严格共用 composer.lock 确保多环境一致性。

composer.json 里不能直接写环境判断
Composer 本身不支持 if env === 'prod' 这种逻辑,composer.json 是静态声明式配置,所有字段在 install/update 时就被锁定。想靠它自动切换依赖或脚本,会踩坑。
常见错误现象:composer install 在测试机和生产机装出不同包,或者 require-dev 里的工具意外进生产镜像。
- 别把生产环境必须的包(比如
ext-redis)只塞进require-dev—— 它真不会被装上 - 别在
scripts里硬编码php test.php,然后指望换环境就自动跳过——脚本全都会执行 -
config.platform可以伪造扩展版本,但骗不过运行时真实缺失的扩展,比如没装ext-gd却设"ext-gd": "8.2.0",运行时报Call to undefined function imagecreate()
用 COMPOSER_DEV_MODE 控制 require-dev 是否生效
这是 Composer 原生支持的开关,比改 composer.json 更可靠。它决定 require-dev 区块是否参与依赖解析和安装。
使用场景:CI 构建生产镜像时跳过测试工具,本地开发保留全部。
- 生产部署时加环境变量:
COMPOSER_DEV_MODE=0 composer install --no-dev(--no-dev优先级更高,但变量更灵活) - Dockerfile 中写:
ENV COMPOSER_DEV_MODE=0,再跑composer install,require-dev自动失效 - 注意:如果
require-dev里有你实际运行时需要的包(比如symfony/var-dumper用于调试),别盲目关掉——它不是“仅测试用”的银弹
环境相关逻辑必须挪到 PHP 运行时
Composer 负责装包,不负责行为分支。真正要区分环境的地方,比如数据库配置、日志级别、缓存驱动,得在 PHP 代码里读取环境变量判断。
典型错误:把 .env 文件路径写死在 autoload.files 里,结果测试环境加载了生产 .env。
- 用
getenv('APP_ENV')或$_SERVER['APP_ENV']判断,而不是靠 Composer 加载哪个文件 - 不要在
autoload.files中写"config/{$_ENV['APP_ENV']}.php"—— Composer 不解析 PHP 变量 - 推荐方式:统一加载
.env(用vizual/vlucas/phpdotenv),再让框架/应用代码根据APP_ENV值选配置 - 性能影响:dotenv 解析是 I/O 操作,生产环境建议用
phpdotenv的loadEnv()+ 编译后缓存,避免每次请求都读文件
vendor 目录不该进 Git,但 lock 文件必须提交
很多人以为删掉 vendor 就能“隔离环境”,其实错在忽略了 composer.lock 的作用。
关键点:composer.lock 锁定了所有包(含 require-dev)的精确版本和哈希值。它才是多环境一致性的核心。
- 测试机和生产机必须共用同一份
composer.lock,否则composer install装出来的包可能不一致 -
composer update应该只在开发机运行,并提交更新后的composer.lock - 生产部署只允许
composer install(不带--update),且确保COMPOSER_DEV_MODE设置正确 - 容易忽略:Git 忽略
vendor/但没忽略composer.lock—— 如果它被意外删了,整个环境一致性就断了
composer.json,而在你什么时候读 APP_ENV、怎么用 COMPOSER_DEV_MODE、以及是否严格维护 composer.lock 的提交节奏。这三个点漏掉任何一个,多环境就只是看起来分开了。










