composer 不处理开发环境差异,仅按 lock 文件装包;多环境配置依赖 --no-dev、config.platform 和运行时代码协同实现。

Composer 本身不处理开发环境差异,它只按 lock 文件装包;所谓“多环境配置”其实是靠 --no-dev、config.platform 和运行时代码协同实现的。
为什么 --no-dev 是生产部署第一道防线
漏加 --no-dev 是线上事故最常见原因:phpunit、symfony/debug、laravel-debugbar 这类包会直接进 vendor/,带来安全暴露、性能拖慢、甚至因扩展缺失导致 Fatal error: Call to undefined function xdebug_is_enabled()。
-
composer install默认照composer.lock安装——而 lock 文件里有没有 dev 包,取决于上次composer update是不是加了--no-dev - CI 构建前必须跑
composer update --no-dev --lock并提交新 lock;否则composer install --no-dev也无效 -
--no-dev不影响autoload-dev的定义,但不会安装对应包;如果代码里硬写了new \Tests\FooTest(),运行时仍会报Class not found - Dockerfile 和 GitHub Actions 中必须显式写死该参数,不能依赖
COMPOSER_DEV_MODE=0等变量——优先级低且不易追踪
config.platform 怎么避免“本地能装、线上报错”
当本地 PHP 是 8.2、线上是 8.1,或本地有 ext-xdebug、线上没有时,Composer 可能因平台不匹配拒绝安装某些包,或装上后运行时报函数不存在。这不是 bug,是校验机制在起作用。
围绕关键发现、作用机制、临床相关性及研究局限性展开讨论。适用于撰写或优化任何生物医学论文的“讨论(Discussion)”部分——包括结果解读、与既往文献关联、阐释意外发现、界定研究局限性,以及撰写结论。当用户输入以下任一指令时也会自动触发该功能: - “write my discussion” - “help me discuss my findings” - “how do I compare to prior studies” - “write the limitations par
- 在
composer.json中写:"config": { "platform": { "php": "8.1.0", "ext-gd": "8.1.0", "ext-xdebug": "3.1.5" } } - 版本号必须是具体值,
"php": "^8.1"或"~8.1"会被忽略 - 它只影响依赖解析阶段(即选哪些包能装),不解决运行时缺失扩展的问题——真实没装
ext-gd,imagecreate()还是崩 - 上线构建时更干净的做法是加
COMPOSER_PLATFORM_CHECK=0 composer install --no-dev,比改platform更可控
autoload-dev 和 require-dev 不是一回事
很多人以为删掉 require-dev 就能“隔离测试代码”,其实混淆了两个概念:包是否安装,和类路径是否注册,是两步操作。
-
autoload-dev只是告诉 Composer “这些路径下的类可以被自动加载”,但它不决定包是否存在于vendor/ - 用
--no-dev安装后,vendor/autoload.php仍含autoload-dev映射——除非你额外执行composer dump-autoload --no-dev - 如果测试工具包(如
phpunit/phpunit)被require-dev引入,但你的控制器里写了dump($data)且用了symfony/var-dumper,那它就是运行时依赖,不能只放require-dev - 检查方式很简单:
grep -r "symfony/var-dumper" src/—— 如果命中,就得挪进require
别碰多 composer.json 这条线
搞 composer-prod.json、composer-dev.json 或用脚本替换文件,短期看似灵活,长期必然导致 composer.lock 冲突、CI 构建不可重现、“在我机器上能跑”泛滥。
- Composer 不支持多配置文件切换;
-c composer-prod.json会完全绕过项目级配置,包括autoload和scripts,极易出错 - 所有环境共用一份
composer.json+composer.lock,才是可重现部署的底线 - 真要彻底隔离依赖(比如 prod 必须用 A 包、dev 必须用 B 包),唯一可靠方案是拆成独立包 +
path类型仓库,而不是分裂配置文件 -
vendor/不该进 Git,但composer.lock必须提交——它是多环境一致性的唯一锚点
最容易被忽略的其实是 lock 文件的生成时机:它不是“写完 composer.json 就自动生成”的快照,而是由 composer update 的参数决定内容。CI 脚本里少一个 --no-dev,就可能让整个生产镜像带上调试入口。










