require-dev只能写Packagist包名与语义化版本,不可用路径或URL;必须通过composer require --dev添加,生产环境需用--no-dev跳过安装。

require-dev 里只能写包名 + 版本,不能写路径或 URL
直接把 GitHub 地址、本地 ./packages/mylib 或 dev-main 分支名塞进 require-dev 字段,Composer 会报错:Could not find package xxx。Packagist 是唯一默认源,所有包名必须和 packagist.org 上完全一致(大小写敏感),比如 phpunit/phpunit,不是 phpunit 或 PHPUnit/PHPUnit。
版本号要符合语义化约束规则:
-
^9.5:允许升级到9.x最高兼容版(如9.6.10),但不会升到10.0 -
~9.5.0:只允许补丁+小版本更新(9.5.99为止),比^更保守 -
dev-main:需额外配置"minimum-stability": "dev",且上线前必须换掉 —— 它不锁定提交,每次 install 都可能拉不同代码
composer require --dev 是唯一推荐的添加方式
手动编辑 composer.json 的 require-dev 区块再跑 composer install 虽然可行,但容易漏掉依赖树解析或 autoload 注册。正确做法是直接执行命令:
-
composer require --dev phpunit/phpunit:^9.5:写入require-dev并立即安装,同时更新composer.lock -
composer require --dev friendsofphp/php-cs-fixer:^3.0 --no-install:只改 JSON 不装包,适合 CI 流水线分步操作 - 误加到
require了?删掉vendor和composer.lock,改完 JSON 后重跑composer install—— 别试图用update修复,边界容易混乱
require-dev 包在生产环境必须被跳过
CI 构建或 Docker 部署时若漏掉 --no-dev,会导致 phpunit、phpstan 这类工具被装进生产镜像,带来三重风险:磁盘膨胀、攻击面扩大、因扩展缺失(如 pcov)引发启动失败。
验证是否生效的方法很简单:
- 部署后进容器执行
ls vendor/phpunit,应返回不存在 - 运行
composer show --dev,只在开发机上能看到列表,生产机执行会报错或空输出 - 如果某包(如
symfony/var-dumper)在config/dev/debug.php中被引用,但没放require-dev,prod 环境就会抛Class not found
autoload-dev 的存在常被忽略
require-dev 只控制“是否安装”,不等于“能否加载”。很多 dev 包(如 phpunit/phpunit)在自身 composer.json 里声明了 "autoload-dev",这意味着:即使包已安装,它的测试辅助类(如 PHPUnit\Framework\MockObject\MockBuilder)也不会进主 autoloader,除非项目也启用 autoload-dev。
如果你在测试中用了这些类却报错,检查两处:
- 项目根目录
composer.json是否有"autoload-dev"块并已运行composer dump-autoload - CI 环境是否禁用了
autoload-dev(某些企业镜像会全局设"optimize-autoloader": true,它默认跳过autoload-dev)


















