应将phpunit等开发专用包放入require-dev,线上部署时用--no-dev跳过安装,避免安全风险、性能下降及运行时错误。

直接用 require-dev 字段存开发专用包,线上部署时加 --no-dev 参数跳过安装——这是最稳、最轻量、也最容易被忽略的分界线。
怎么把 PHPUnit 这类工具只留在开发环境
所有只在写代码、跑测试、格式化时才需要的包,必须进 require-dev,不能混进 require。比如:
-
phpunit/phpunit、friendsofphp/php-cs-fixer、mockery/mockery都该走composer require --dev - 执行
composer require --dev phpunit/phpunit后,它会自动写进composer.json的require-dev块,并更新composer.lock - 本地
composer install默认装两者;但只要线上跑composer install --no-dev,这些包就根本不会解压进vendor/
为什么线上漏掉 --no-dev 会出事
不是“少装几个包”那么简单,而是直接影响安全、性能和运行逻辑:
围绕关键发现、作用机制、临床相关性及研究局限性展开讨论。适用于撰写或优化任何生物医学论文的“讨论(Discussion)”部分——包括结果解读、与既往文献关联、阐释意外发现、界定研究局限性,以及撰写结论。当用户输入以下任一指令时也会自动触发该功能: - “write my discussion” - “help me discuss my findings” - “how do I compare to prior studies” - “write the limitations par
- 像
barryvdh/laravel-debugbar或symfony/debug这类包,一旦被装上又没关开关,可能把敏感信息打到响应里 -
phpunit本身体积不小,多装几十MB vendor,拉镜像变慢,磁盘占用上升,CI 构建时间拉长 - 某些 dev 包依赖的扩展(如
pcov)在线上缺失,导致composer install直接失败 - 更隐蔽的问题:如果某个包在
require-dev里定义了autoload-dev,而你代码里又硬引用了它的测试类(比如new \Tests\FooTest()),那--no-dev后连Class not found都不是报错,是运行时直接崩
CI/CD 脚本里怎么写才不翻车
别靠人肉记命令,把环境逻辑固化进脚本里:
- 生产部署脚本必须明确写成:
composer install --no-dev --optimize-autoloader - CI 测试阶段可以装 dev 包,但得加
--prefer-dist加速下载,避免反复 clone - 千万别在 CI 里用
composer update—— 它会改composer.lock,破坏本地与线上的一致性;应该只用composer install - 如果要用不同 PHP 版本做兼容检查,优先配
config.platform.php,而不是搞两个composer.json文件——后者会让composer.lock失效,引发“本地能跑线上炸”的经典故障
autoload-dev 和 --no-dev 的关系容易被误解
--no-dev 只控制「是否下载并解压包」,它不删配置、不屏蔽 autoload 规则:
- 即使你用了
--no-dev,composer.json里的autoload-dev段落依然存在,composer dump-autoload也会读它 - 但问题在于:如果
autoload-dev映射的是一个根本没装进vendor/的包(比如phpunit的src/目录),那自动加载器生成的映射就是空的——运行时找不到类,不是因为没注册,是因为目录压根不存在 - 所以真正要检查的,不是 autoload 配置有没有,而是「这个命名空间对应的物理路径,此刻是不是真实存在于文件系统中」
最常被绕开的点是:--no-dev 不等于「禁用所有 dev 行为」,它只是物理层面不放包进来。一旦代码里有对 dev 包的强依赖(比如构造函数参数类型声明、use 语句、或 class_exists() 判断),就得靠条件加载或接口抽象来兜底,光靠 Composer 参数解决不了。










