Composer 保姆级教程:依赖冲突、版本锁、国内镜像避坑(2026 实战版)
Composer 是 PHP 生态的"包管理命门",但大多数人卡住不是因为不会 require,而是栽在三个地方:依赖冲突看不懂、composer.lock 乱动、国内镜像配了跟没配一样。这篇从原理到命令,一次讲透。
一、先搞清楚两个核心命令的区别(90% 的事故源头)
| 命令 | 行为 | 什么时候用 |
|---|---|---|
composer install |
严格按 composer.lock 还原依赖,lock 不存在才按 json 算 |
生产部署、CI、团队协作拉代码 |
composer update |
重新解析 composer.json 约束,算出新版本,重写 composer.lock |
本地主动升级依赖、解决冲突后重算 |
⚠️ 生产环境跑
update= 主动引入未知版本 = 线上炸锅的经典操作。
正确姿势
- 开发机:
composer update或composer update vendor/pkg - 服务器 / CI:
composer install --no-interaction --prefer-dist --optimize-autoloader
二、版本约束与稳定性:冲突为啥会发生
Composer 用 SAT 求解器找"所有包都能兼容"的一组版本,找不到就报 Your requirements could not be resolved。
1. 版本符号别再混
^2.0→>=2.0 <3.0(收主次版本,收最小版本号不收大版本)~2.3→>=2.3 <2.4(只收补丁)2.5.*→>=2.5.0 <2.6.0- 精确
2.5.1→ 锁死
2. minimum-stability 与 @后缀
默认 "minimum-stability": "stable",所以以下情况会冲突:
- 你要
laravel/sanctum: ^4.0,但该包只有v4.0.0-rc1 - 私有包没打 tag,只有
dev-main
解法(按优先级)
- 单包放行:
"vendor/pkg": "1.2.3@beta"或"dev-main as 1.0.x-dev" - 全局放宽:
"minimum-stability": "beta", "prefer-stable": true(有 stable 仍选 stable)
三、依赖冲突排查:别再无脑删 vendor
报错 Conclusion: don't install xxx v2.0 或 requires A ^1.0 but B requires A ^2.0,按下面顺序来:
bash
# 1. 看是谁把某个包拽进来的
composer why vendor/package
# 2. 看依赖树(反向追踪)
composer depends -t vendor/package
# 3. 模拟:升级某包会不会撞墙
composer update vendor/pkg --dry-run
# 4. 实在要连带升级下游
composer update vendor/pkg --with-all-dependencies
常见套路:
- A 包锁
symfony/console: ^4.4,B 包要^5.0→ 要么降 B,要么升 A 到兼容 Symfony 5 的版本 - PHP 版本不匹配:lock 里是 PHP 8.1 编译的扩展,本地 7.4 → 改
platform.php或换 PHP,别盲目update
composer.json 里锁定平台版本,避免"我机器上能跑":
json
"config": {
"platform": { "php": "8.1.0" }
}
四、composer.lock 的真相:该提交还是该删
- 应用项目(Laravel / 业务系统) :必须提交
composer.lock到 Git,保证所有人、CI、生产装到字节级一致的版本。 - 库项目(被别人 require 的 package) :通常不提交 lock,让使用者自己解依赖。
lock 冲突合并时
csharp
git checkout --theirs composer.lock
composer install # 能装就接受,不能装再删了重算
换镜像后 lock 里还记着旧源地址?
csharp
composer update --lock # 只刷新 lock 元数据,不升版本
否则可能出现 hash 校验失败或静默回退官方源。
五、国内镜像:2026 年还能用的只有这几个
默认源 packagist.org 在国内直连基本卡死在 Resolving dependencies,换镜像是刚需不是优化。
可用镜像(HTTPS,末尾斜杠不能省)
ruby
# 阿里云(首选)
composer config -g repo.packagist composer https://mirrors.aliyun.com/composer/
# 腾讯云
composer config -g repo.packagist composer https://mirrors.cloud.tencent.com/composer/
# 华为云
composer config -g repo.packagist composer https://mirrors.huaweicloud.com/repository/php/
中科大:https://packagist.mirrors.ustc.edu.cn/
已死别再抄
https://packagist.phpcomposer.com(2023 下线)https://packagist.laravel-china.org(同步不稳)- 任何
http://开头(Composer 2.5+ 强制 HTTPS,会静默回退官方源)
配完必做三件事
bash
composer clear-cache # 清旧元数据,不然还打老源
composer config -g repo.packagist # 回显确认不是 packagist.org
composer diagnose # 看 Repo.packagist 行指向谁
项目级 > 全局(CI / 团队推荐)
全局配置在宝塔 www 用户、GitLab Runner 用户、本地 root 之间经常不生效。进项目根目录:
arduino
composer config repo.packagist composer https://mirrors.aliyun.com/composer/
写进 composer.json 的 repositories,新人 clone 下来自动走镜像,不依赖本机全局。
临时切回官方源调试:
composer config -g repo.packagist https://packagist.org
六、高频踩坑清单(直接对照)
- 卡在 Resolving dependencies → 没配镜像 / 缓存没清 / 用了 http 源
- SSL handshake failed → 不是镜像问题,是 PHP
openssl.cafile没配或系统 CA 过期 - sudo composer 跟当前用户行为不一样 → 全局配置写进 root 的
COMPOSER_HOME,换用户等于没配 - CI 每次都重新下包超慢 → 没开
prefer-dist+ 没缓存~/.composer/cache - update 后本地能跑线上报错 → 线上用了
install但 lock 没提交,或 PHP 平台版本不一致 - require 新包报 could not resolve → 先
composer show vendor/pkg --all看它到底发了哪些版本和 stability
七、一条最小安全工作流
bash
# 本地加依赖
composer require monolog/monolog:^2.0
# 冲突就 why + dry-run,别删 lock 裸 update
composer why monolog/monolog
composer update monolog/monolog --with-all-dependencies --dry-run
# 没问题再真跑,提交 json 和 lock
composer update monolog/monolog --with-all-dependencies
git add composer.json composer.lock
git commit -m "feat: add monolog"
# 服务器 / CI
composer install --no-interaction --prefer-dist --optimize-autoloader
把上面四条线(install/update 边界、版本与 stability 语义、lock 提交策略、镜像配置+清缓存)记住,Composer 90% 的红色报错你都能在 5 分钟内定位到是哪一层的问题,而不是反复删 vendor 碰运气。