学完这篇你能把 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