composer.lock是PHP项目依赖的可执行快照,强制composer install精确还原version、dist.sha256、source.reference及完整依赖树,完全忽略composer.json版本约束,缺失即报错拒绝执行。

Composer 本身不提供“元数据快照备份”这个功能,composer.json 和 composer.lock 就是它的元数据与依赖快照——你不需要额外备份命名,但必须严格按规范写好 name、version、Git Tag 和 branch-alias,否则整个快照链会断裂。
composer.json 的 name 字段必须小写+短横线+斜杠分隔
这是最常被忽略的硬性门槛。Composer 2.x 会直接中止操作,不是警告。
-
name必须是vendor/package格式,全小写,只允许-、.、_作分隔符,且不能以数字开头 - 错例:
"MyOrg/MyPackage"、"myorg.my_package"、"123pkg"→ 全部触发Invalid package name - 对例:
"myorg/my-package"、"acme.http-client"、"vendor_name/some_tool" - 发布到 Packagist 前,先跑
composer validate,它比install更早暴露命名问题
本地 path 包的 version 字段决定实际解析结果
你写 composer require myorg/my-package:1.2.3 没用,Composer 不会去读你命令里的 1.2.3,它只认目标包根目录下 composer.json 里写的 "version": "1.2.3"(注意:不带 v 前缀)。
- 没写
version?默认当dev-main处理,composer.lock里记录的也是"dev-main",不是你期望的语义化版本 - 写了
"version": "v1.2.3"?Composer 会静默忽略v,但若同时存在 Git tagv1.2.3,可能引发歧义;统一用"1.2.3" - 改了本地
composer.json的version,必须运行composer update myorg/my-package --with-all-dependencies,install不会重读 - 确认生效:打开
composer.lock,搜该包名,看"version"字段是否为你写的值,且"source"→"type"是"path"
Git Tag + branch-alias 才能让 dev-main 被 ^/~ 约束识别
dev-main 本身不是版本,只是分支快照。没有 branch-alias,你就没法在主项目里写 "^1.0" 安全升级——Composer 会报“no matching package found”。
- 在本地包的
composer.json里加:"extra": {"branch-alias": {"dev-main": "1.0.x-dev"}} - Tag 必须是轻量 Tag(
git tag 1.2.3),不能是附注 Tag(git tag -a);结尾不能带#main或路径 - Tag 名建议和
branch-alias对齐:1.2.3对应"1.0.x-dev",2.0.0对应"2.0.x-dev" - 私有仓库要确保
auth.json存在且含有效 token;URL 中不要出现@username,否则认证跳过,Tag 查不到
composer.lock 是唯一可信的快照,但它的有效性依赖前三个环节
composer.lock 文件本身格式没问题,但它记录的内容是否可靠,取决于 name 合法、version 显式声明、Tag 与 branch-alias 配套。三者缺一,lock 文件就变成“看起来稳定,实则不可复现”的陷阱。
- CI 流水线必须提交
composer.lock,且执行composer install --no-dev --prefer-dist - 别信
composer show显示的版本——它可能来自缓存或 symlink,要以composer.lock和vendor/autoload.php实际加载为准 - 多人协作时,如果 A 提交了 lock,B
update后没提交,Cinstall就可能装出不同版本——因为 lock 文件没同步 - 想验证快照一致性?删掉
vendor和composer.lock,只留composer.json,再composer install,看结果是否和原 lock 一致











