minimum-stability 是包级别默认稳定性设置,仅在未显式声明时生效;prefer-stable=true 才真正优先选用稳定版本;stability-flags 和 lock 文件中的 version 字段共同决定最终安装的稳定性。

minimum-stability 是 package 级别的稳定性开关,不是全局锁
很多人以为设了 minimum-stability 就能“强制所有包都用 stable”,其实它只起默认作用——当某个包没在 require 里显式声明自己的稳定性(比如没写 @dev),Composer 才会按这个值去筛选可用版本。一旦你写了 "monolog/monolog": "2.x-dev",minimum-stability 就完全不拦着。
实操建议:
- 默认设成
"minimum-stability": "stable",这是生产环境最安全的起点 - 真要引入 dev 版本时,必须在
require或require-dev中显式带上@dev、@rc等后缀,例如:"phpunit/phpunit": "^10.5@dev" - 不要为了临时装一个 dev 包就临时把
minimum-stability改成dev,否则可能连带拉进一堆不稳定依赖
prefer-stable=true 才是真正“倾向稳定版”的配置
minimum-stability 控制“能选哪些”,prefer-stable 控制“优先选哪个”。比如两个版本都合法:2.3.0(stable)和 2.4.0-RC1(RC),若 minimum-stability 是 RC,默认会装 RC;但加上 "prefer-stable": true,Composer 就会选 2.3.0。
常见错误现象:
- 明明
minimum-stability是stable,却装了alpha版——大概率是某个依赖的composer.json里写了"minimum-stability": "alpha",且你没开prefer-stable,导致它“传染”了你的解析逻辑 - CI 构建结果不一致——本地开了
prefer-stable,CI 没开,导致选到不同版本
务必在 composer.json 顶层加这一行:"prefer-stable": true
dev-main 和 stability flags 的冲突很隐蔽
PHP 8.2+ 项目中,如果用了 dev-main 这类分支别名,又没配好稳定性标记,Composer 可能直接拒绝安装,报错:Could not find a version of package xxx matching your minimum-stability。
原因在于:分支别名本身没有内置稳定性,必须靠 stability-flags 或显式后缀兜底。
实操建议:
- 避免直接写
"vendor/pkg": "dev-main",改用带标记的写法:"vendor/pkg": "dev-main as 999.999.999"(占位版本号) + 配合stability-flags - 更稳妥的做法是:在
composer.json加"stability-flags": { "vendor/pkg": "dev" },再写"vendor/pkg": "dev-main" - 注意
stability-flags不继承,父项目设了,子依赖不会自动获得同样策略
lock 文件里的 stability 信息容易被忽略
composer.lock 里每个包条目都有 version 字段,像 "version": "dev-main#abc123" 或 "version": "3.2.0-RC1",它真实记录了当时解析出的稳定性。下次 composer install 会严格按这个装,哪怕你后来调高了 minimum-stability,也不会自动降级。
这意味着:
- 换环境部署前,别只看
composer.json,一定要确认composer.lock里关键包的version字段是否符合预期 - 想彻底清理历史不稳定版本?删掉
composer.lock+vendor,再composer install(前提是composer.json已正确配置minimum-stability和prefer-stable) - 团队协作时,
composer.lock必须提交,否则每人install出来的稳定性可能不一致
稳定性不是设完配置就一劳永逸的事,它藏在 composer.json 的三处字段里、composer.lock 的每个 version 值里,还受依赖包自身配置牵连——漏掉任何一环,都可能在某次更新后突然冒出 alpha 版本。










