必须用composer.json声明、composer.lock锁定、vendor/autoload.php加载,三者缺一不可;手动拷包、硬编码require、直接改vendor代码会导致协作和部署失败。

必须用 composer.json 声明、composer.lock 锁定、vendor/autoload.php 加载,三者缺一不可;手动拷包、硬编码 require、直接改 vendor 里的代码,都会导致协作和部署失败。
怎么写对自定义包的 composer.json 依赖项
自定义包(比如你公司私有 Git 仓库里的 acme/utils)不能只写个 URL 或本地路径就完事。Composer 要求它具备合法的包元信息,且必须通过 Packagist 兼容的仓库或 repositories 显式声明。
- 若包托管在 GitHub/GitLab,先确保其根目录有合法的
composer.json(含name、version或autoload),例如:{"name":"acme/utils","autoload":{"psr-4":{"Acme\":"src/"}}} - 在项目根目录的
composer.json中,用repositories指明来源,再在require中引用:{ "repositories": [ { "type": "vcs", "url": "https://gitlab.example.com/acme/utils" } ], "require": { "acme/utils": "dev-main" } } - 避免写
"acme/utils": "dev-master"——master分支名已过时,Git 默认分支可能是main;也不要用"*"或"@dev",它们绕过版本约束,破坏可重现性
composer install 和 composer update 在私有包场景下行为差异
私有包没进 Packagist,composer install 会失败,除非 composer.lock 已记录该包的 commit hash 和源地址;而 composer update 会尝试从 repositories 拉取最新元数据——但前提是能连上你的 Git 服务器,且认证通过。
- CI/CD 或新同事首次拉代码后,必须先确保
composer.lock已提交,否则composer install会报错:Could not find package acme/utils - 执行
composer update acme/utils时,Composer 会重新解析acme/utils的composer.json,并更新其子依赖;但不会动其他包——这点比全量update安全得多 - 如果 Git 仓库需要 SSH 认证,确保运行 Composer 的用户已配置好 SSH key;HTTP 方式则需提前设好
git config --global credential.helper store或用auth.json
为什么 autoload 配置不能省,尤其对私有包
私有包通常不走 Packagist 的自动索引,它的类不会被默认加载。哪怕包已下载到 vendor/acme/utils,没配 autoload 就等于“存在但不可用”。
- 推荐在私有包自己的
composer.json里写psr-4(如"Acme\":"src/"),而不是让下游项目在autoload里手动映射——后者耦合高、易遗漏 - 若私有包暂无
autoload字段,下游项目可在自身composer.json的autoload下加psr-4或classmap,但每次包结构变都要同步改,不健壮 - 改完
autoload后,必须运行composer dump-autoload,否则vendor/autoload.php不会更新映射表
上线部署时最容易忽略的三个点
私有包让部署链路更脆弱:它依赖网络、认证、Git 状态,而这些在生产环境常被限制或误配。
-
--no-dev参数必须加,但更要确认私有包本身没被错误地塞进require-dev—— 否则上线时它根本不会装 - CI 构建机若没配 Git 凭据,
composer install会卡在 clone 私有仓库那步;建议用 deploy token 或 SSH deploy key,而非个人账号 - 不要把
vendor目录打包上传,也不要传composer.lock以外的锁文件;composer.lock必须包含私有包的source字段(含 url + reference),否则部署时无法还原
私有包管理真正的难点不在“怎么装”,而在“怎么让所有人装得一模一样”。一旦 composer.lock 里 reference 是 commit hash,而 Git 仓库被 force push 过,整个环境就不可复现——这点比公开包更致命,也最难排查。


















