Composer不支持环境感知装包,仅靠require与require-dev分离及安装时显式传参实现分环境管理;默认安装含require-dev包,需--no-dev跳过,否则生产环境会误装phpunit等开发依赖。

Composer 不支持按 APP_ENV 或服务器 hostname 自动切换依赖,所谓“分环境装包”,本质是靠 require 和 require-dev 的职责分离 + 安装时显式传参控制,不是环境感知,而是命令驱动。
为什么 composer install 默认会装 phpunit、var-dumper 这些包
因为它们被写在 require-dev 里,而 composer install 默认不加 --no-dev 就会把 require-dev 全部装进去——它不看你是本地还是线上,只认命令参数。
-
require-dev中的包参与composer install的默认安装流程,和require一样走解析、下载、解压、autoload 注册全流程 - 常见翻车点:Dockerfile 里只写
composer install,没加--no-dev,结果生产镜像里塞进phpunit/、sebastian/、symfony/var-dumper/ -
composer.lock文件里会同时记录packages(require)和packages-dev(require-dev),但--no-dev只跳过后者安装,不删 lock 里的记录
composer install --no-dev 到底跳过了什么
它跳过 require-dev 声明的所有包的安装,也跳过这些包注册的 autoload 规则(比如 autoload-dev 里定义的 "Tests": "tests/"),但不会影响 require 包的行为或你的业务代码。
- vendor/ 目录下不会出现
phpunit/phpunit、mockery/mockery等目录 -
vendor/composer/autoload_dev.php文件不会生成——这是关键,漏删这个文件会导致Class not found错误 - 如果你的代码里写了
new TestsFooTest(),即使--no-dev成功,运行时仍会报错;这不是 Composer 的问题,是你代码逻辑越界了 -
--no-dev不影响config.platform、scripts或其他配置字段,它只作用于依赖安装阶段
Docker 和 CI 里怎么避免漏掉 --no-dev
不能靠记忆或环境变量,必须硬编码在命令里。CI 缓存、Docker 构建、PHAR 打包,每个环节都要显式声明,否则前一步缓存污染后一步部署。
- Dockerfile 中必须写死:
RUN composer install --no-dev --optimize-autoloader --no-scripts,别用ENV COMPOSER_NO_DEV=1,那会影响所有后续命令 - GitHub Actions / GitLab CI 的缓存 key 必须包含
--no-dev标志,例如:composer-${{ hashFiles('**/composer.lock') }}--no-dev,否则缓存复用时可能把 dev 包带进生产构建 - CI 测试阶段要用完整安装:
composer install && ./vendor/bin/phpunit;但构建生产镜像那步,必须切回--no-dev,两者不能混用 - Box 打包 PHAR 时,除了
--no-dev,还得手动删掉vendor/composer/autoload_dev.php,否则 PHAR 加载时仍会尝试读它
容易被忽略的 autoload 边界问题
autoload-dev 不是给 PHPUnit 用的,是给你写的测试类用的;它只在你本地跑完整 composer install 后才生效,生产环境即使配置再全也没用。
- 如果你的
tests/目录用了MockeryLegacyMockInterface,除了把mockery/mockery放进require-dev,还得确保autoload-dev包含"Tests\": "tests/",否则new TestsFooTest()仍找不到类 -
composer dump-autoload --classmap-authoritative在生产环境执行时,不会扫描autoload-dev路径,哪怕你忘了加--no-dev,只要 vendor 里没装那些包,就扫不到 - 不要试图用
"config": {"dev": false}一劳永逸——它会让本地开发也永远装不上 dev 包,连composer require --dev都失效,得不偿失


















