学完这篇你能把 Composer 从「只会 composer require」用到能自己配自动加载规则、写清版本约束、把公司私有仓库拉进项目里。
第一步:搞清自动加载的三个入口
Composer 的自动加载全部写在 composer.json 的 autoload 段里,三种主流写法对应三类代码:
{
"autoload": {
"psr-4": {
"App\\": "src/",
"App\\Admin\\": "src/Admin/"
},
"classmap": ["legacy/", "lib/Old_Thing.php"],
"files": ["src/helpers.php", "src/constants.php"]
},
"autoload-dev": {
"psr-4": { "Tests\\": "tests/" }
}
}
- psr-4:新代码用这个。
App\Foo\Bar 会自动映射到 src/Foo/Bar.php,一个前缀可以配多个目录(用数组)。
- classmap:老项目、下划线命名、一个文件多个类的代码用它,Composer 会扫描目录生成类名→文件路径的静态表。
- files:纯函数、常量定义用这个,每次请求都会 include,别放重的逻辑。
改完 autoload 段必须执行一次:
composer dump-autoload # 重新生成 vendor/composer/autoload_*.php
composer dump-autoload -o # 生成 classmap,生产环境用
composer dump-autoload -a # --classmap-authoritative,只信 classmap,不再走文件系统查找
-a 在线上最值得开:类找不到就直接报错,不再挨个目录 stat 文件,I/O 明显下降。
注意:-o / -a 之后新增了类文件不会自动被发现,必须再 dump 一次。CI 里部署脚本要带上这一步,否则「本地能跑,线上 Class not found」。
第二步:写对版本约束
常用约束按推荐程度排:
| 写法 | 含义 |
|---|
^1.2.3 | >=1.2.3 <2.0.0,允许小版本升级,最常用 |
~1.2.3 | >=1.2.3 <1.3.0,只允许补丁级 |
1.2.* | 等价于 >=1.2.0 <1.3.0 |
>=1.0 <2.0 | 显式区间,适合跨大版本兼容的库 |
dev-main / 1.0.x-dev | 分支约束,配合 @dev 稳定性标记 |
安装时直接指定:
composer require monolog/monolog:^3.0
composer require phpunit/phpunit:^10.0 --dev
依赖装不上时不要靠猜,用这两条命令看到底是谁挡住了:
composer why-not monolog/monolog 3.0
composer show -t # 打印依赖树
composer outdated --direct
如果某个包只有 beta 版,可以在包名后加稳定性后缀 :^2.0@beta,或者在根部统一放宽:
{ "minimum-stability": "stable", "prefer-stable": true }
注意:^0.3.1 的实际含义是 >=0.3.1 <0.4.0,因为 0.x 被视为不稳定版本,别以为它会升到 0.9。另外 composer.lock 必须提交进仓库,它是团队和线上环境版本一致的唯一保证。
顺带一个高频坑:本地 PHP 版本和线上不一致时,可以锁死平台版本,避免解析出线上跑不了的依赖:
composer config platform.php 8.1.0
第三步:接入私有包
私有包本质还是 Composer 包,区别只是「从哪里拿」。在 composer.json 加 repositories:
1)Git 仓库(VCS 方式)
{
"repositories": [
{ "type": "vcs", "url": "git@gitlab.company.com:lib/payment-sdk.git" }
],
"require": { "company/payment-sdk": "^1.4" }
}
2)本地路径(开发调试最省事)
{ "repositories": [ { "type": "path", "url": "../payment-sdk", "options": { "symlink": true } } ] }
软链方式下改完私有包代码立刻生效,不用 composer update。
3)私有 Packagist(Satis / Private Packagist / Repman 自建)
{ "repositories": [ { "type": "composer", "url": "https://packagist.company.com" } ] }
认证写在项目根的 auth.json,或用环境变量:
{
"http-basic": { "packagist.company.com": { "username": "deploy", "password": "TOKEN" } },
"github-oauth": { "github.com": "ghp_xxx" }
}
也可以整体塞进环境变量:
export COMPOSER_AUTH='{"http-basic":{"packagist.company.com":{"username":"deploy","password":"TOKEN"}}}'
注意:auth.json 绝不能提交到仓库(把它加进 .gitignore)。CI 里用环境变量注入。用 SSH 方式拉包时,部署机需要配好 deploy key 和 known_hosts,否则会卡在交互式确认上。
第四步:上线前的检查清单
composer validate --strict # 校验 composer.json 语法与规范
composer diagnose # 检查网络、代理、镜像配置
composer install --no-dev -o -a --no-scripts # 生产安装
composer audit # 已知漏洞扫描
国内网络慢可以换镜像:composer config -g repo.packagist composer https://mirrors.aliyun.com/composer/。依赖解析爆内存时加 COMPOSER_MEMORY_LIMIT=-1。
注意:生产环境用 composer install(读 lock),不要用 composer update,后者会顺带升级依赖,等于在线上做一次未经测试的变更。
另外提醒一句:并不是所有 PHP 系统都需要 Composer。像 Clara BBS 这类无框架轻量级论坛系统,明确不需要 Composer、不需要命令行,上传文件后访问 install 走安装向导即可,插件靠运行时钩子加载、保存即生效。本文的内容适用于你自己写的项目,或者引入了 Composer 依赖二次开发的场景。
小结
- 自动加载三件套:新代码 PSR-4、老代码 classmap、函数库 files;改完必须
dump-autoload
- 线上加
-o -a 提升类查找性能,代价是新增类要重新 dump
- 版本约束默认用
^,装不上先 composer why-not 而不是瞎改约束
composer.lock 提交,线上只跑 composer install --no-dev
- 私有包三选一:VCS 仓库、path 软链(开发)、自建 composer 仓库(规模化)
- 认证信息走
auth.json 或 COMPOSER_AUTH,永远不进 Git