📦 cli_package_management — 包管理
该示例演示如何用 Composer Skills SDK 在本地 PHP 项目中执行依赖包的全生命周期管理:安装、更新、添加、移除与搜索。
示例定位
cli_package_management 是 Composer CLI 系列示例中的「依赖管理」核心篇。它把日常 composer install / update / require / remove / search 全部映射到 Go SDK 调用,让你能在 Go 程序里以代码方式操控 composer.json 与 vendor/ 目录,而无需手动拼命令行或 shell out。
学完本示例,你将掌握:
- 📥 依赖安装的三种姿势(含 dev、排除 dev、优化 autoload)
- 🔄 全量更新与按包名定向更新
- ➕ 添加普通依赖、指定版本依赖、开发依赖
- ➖ 移除普通依赖与开发依赖
- 🔍 关键字搜索包并解析原始输出
- 🛠️ 自动加载配置的转储与优化(
dump-autoload)
对应 SDK 方法全部位于 pkg/composer 包,集中在 dependencies.go 与 packages.go 两个文件。
完整代码
下面汇总目录下三个示例文件的关键逻辑(已精简重复的日志输出,保留完整调用链)。
01_install_update.go — 安装与更新
package cli_package_management
import (
"fmt"
"log"
"github.com/scagogogo/composer-skills/pkg/composer"
)
func Example01InstallUpdate() {
c, err := composer.New(composer.DefaultOptions())
if err != nil {
log.Fatalf("无法创建Composer实例: %v", err)
}
// 设置工作目录(确保目录下有 composer.json 文件)
projectDir := "/path/to/project" // 根据实际情况修改
c.SetWorkingDir(projectDir)
// 1. 安装依赖(含 dev)
err = c.Install(false, false)
// 2. 安装依赖(不含 dev) —— 第一个参数 noDev=true
err = c.Install(true, false)
// 3. 安装依赖并优化自动加载 —— 第二个参数 optimize=true
err = c.Install(false, true)
// 4. 更新所有依赖(传空切片)
err = c.Update([]string{}, false)
// 5. 更新特定依赖
packagesToUpdate := []string{"monolog/monolog", "symfony/console"}
err = c.Update(packagesToUpdate, false)
// 6. 更新特定依赖(不含 dev)
err = c.Update(packagesToUpdate, true)
// 7. 只更新自动加载配置
err = c.DumpAutoload(false)
// 8. 更新并优化自动加载配置
err = c.DumpAutoload(true)
_ = err // 实际使用时按上面的方式分别处理每个错误
}02_require_remove.go — 添加与移除
package cli_package_management
import (
"fmt"
"log"
"github.com/scagogogo/composer-skills/pkg/composer"
)
func Example02RequireRemove() {
c, err := composer.New(composer.DefaultOptions())
if err != nil {
log.Fatalf("无法创建Composer实例: %v", err)
}
c.SetWorkingDir("/path/to/project")
// 1. 添加普通依赖(不指定版本)
err = c.RequirePackage("monolog/monolog", "", false)
// 2. 添加指定版本的依赖
err = c.RequirePackage("symfony/console", "^5.4", false)
// 3. 添加开发依赖 —— dev=true
err = c.RequirePackage("phpunit/phpunit", "^9.5", true)
// 4. 移除普通依赖
err = c.Remove("monolog/monolog", false)
// 5. 移除开发依赖 —— dev=true
err = c.Remove("phpunit/phpunit", true)
// 6. 使用高级选项添加依赖(options 为 map[string]string)
options := map[string]string{
"--no-update": "",
"--no-progress": "",
"--ignore-platform-reqs": "",
}
err = c.RequirePackageWithOptions("guzzlehttp/guzzle", "^7.0", options)
fmt.Println("使用高级选项添加依赖包 guzzlehttp/guzzle (版本 ^7.0) 成功")
}04_search_package.go — 搜索包
package cli_package_management
import (
"fmt"
"log"
"strings"
"github.com/scagogogo/composer-skills/pkg/composer"
)
func Example04SearchPackage() {
comp, err := composer.New(composer.DefaultOptions())
if err != nil {
log.Fatalf("初始化Composer失败: %v", err)
}
// 关键字搜索,返回 composer 原始文本输出
output, err := comp.Search("logger")
if err != nil {
log.Fatalf("搜索包失败: %v", err)
}
fmt.Println(output)
// 解析输出,逐行提取包名(含 "/" 且非缩进行的首字段)
for _, line := range strings.Split(output, "\n") {
if strings.Contains(line, "/") && !strings.HasPrefix(line, " ") {
parts := strings.Fields(line)
if len(parts) > 0 {
fmt.Printf("- %s\n", parts[0])
}
}
}
// 更精确的搜索
specificOutput, err := comp.Search("monolog")
fmt.Println(specificOutput)
}代码讲解
创建实例与定位项目 🏠
三个文件都以 composer.New(composer.DefaultOptions()) 起步,随后调用 c.SetWorkingDir(projectDir) 把命令的执行目录锁定到目标 PHP 项目。Composer 的所有依赖命令都依赖 composer.json,因此工作目录必须正确。
Install 的两个布尔开关 🚦
c.Install(noDev, optimize) 用两个布尔参数覆盖最常见的安装组合:
noDev=false, optimize=false—— 标准安装,含require-devnoDev=true, optimize=false—— 生产环境安装,跳过开发依赖noDev=false, optimize=true—— 部署期安装,并优化 PSR-4/PSR-0 自动加载映射
Update 的包名切片 🔄
c.Update(packages, noDev) 中,传 []string{} 表示更新全部依赖;传具体包名列表则只更新这些包。noDev 含义与 Install 一致。这是 CI 里「只刷新个别库」的常用手段。
DumpAutoload —— 轻量重建映射 🗂️
c.DumpAutoload(optimize) 对应 composer dump-autoload。它不会改动 vendor/ 内容,只重新生成 vendor/autoload.php 与映射表,速度极快;optimize=true 会合并 PSR-4 命名空间映射以加速生产环境自动加载。
RequirePackage 的版本与 dev 开关 ➕
c.RequirePackage(name, version, dev) 三个参数:
version传""表示让 Composer 自动解析最佳版本dev=true写入require-dev段,适合 PHPUnit、PHPStan 这类工具
它会真实修改 composer.json 并触发依赖解析与安装。
Remove 的 dev 对称性 ➖
c.Remove(name, dev) 与 RequirePackage 严格对称:dev 必须匹配当初添加时使用的段位,否则会从错误的段里找不到条目。
RequirePackageWithOptions —— 精细控制 🎛️
当布尔开关不够用时,c.RequirePackageWithOptions(name, version, options) 接受一个 map[string]string,可传 --no-update、--no-progress、--ignore-platform-reqs 等任意 Composer 原生参数。示例中第 6 步演示的就是「只改 composer.json 不立即安装」的典型用法(--no-update)。
Search 与输出解析 🔍
c.Search(query) 返回 Composer 的原始文本输出,每行一个包(vendor/name 描述)。示例用 strings.Split + strings.Fields 做了轻量解析,提取首字段作为包名。需要更结构化的结果时,可改用 SearchOnlyName、SearchWithType 或返回结构化 *SearchResult 的 SearchInfo。
运行方式
需要本地环境
本系列示例执行本地 composer 二进制,需要本机已安装 PHP 7.4+ 与 Composer 2.0+。若未安装,SDK 的自动安装能力会兜底。示例中的 projectDir 需改成你本机真实存在的 PHP 项目路径。
# 克隆仓库
git clone https://github.com/scagogogo/composer-skills.git
cd composer-skills
# 运行安装/更新示例(确保 /path/to/project 已改为真实项目)
go run examples/cli_package_management/01_install_update.go
# 运行添加/移除示例
go run examples/cli_package_management/02_require_remove.go
# 运行搜索示例(搜索本身不修改项目,最安全)
go run examples/cli_package_management/04_search_package.go建议用一次性测试项目
require / remove 会真实改写 composer.json 与 vendor/,建议先在一个用 composer init 新建的空项目里演练,避免污染生产代码库。
涉及的 SDK 方法
| 方法名 | 所属包 | 文档链接 |
|---|---|---|
New | pkg/composer | /sdk/composer/methods/new |
SetWorkingDir | pkg/composer | /sdk/composer/methods/set-working-dir |
Install | pkg/composer | /sdk/composer/methods/install |
Update | pkg/composer | /sdk/composer/methods/update |
DumpAutoload | pkg/composer | /sdk/composer/methods/dump-autoload |
RequirePackage | pkg/composer | /sdk/composer/methods/require-package |
Remove | pkg/composer | /sdk/composer/methods/remove |
RequirePackageWithOptions | pkg/composer | /sdk/composer/methods/require-package-with-options |
Search | pkg/composer | /sdk/composer/methods/search |
进阶
- 🧪 干跑预演:正式安装/更新前,先用
InstallDryRun、UpdateDryRun、RequireDryRun、RemoveDryRun预览将要发生的变更,不落盘,适合在 CI 里做依赖变更评审。 - 📦 批量操作:单包
RequirePackage/Remove循环效率低,可改用RequireMultiple与RemoveMultiple一次性处理整组依赖;面向合规场景还有带容错的BatchRequire/BatchRemove。 - 🌍 全局维度:操作全局 Composer 环境时,把本示例的方法名前缀加
Global,如GlobalRequire、GlobalRemove,详见 cli_global 示例。 - 🔎 结构化搜索:
Search返回纯文本,需自行解析;想要包名列表可直接用SearchOnlyName,按类型过滤用SearchWithType,需要完整元数据则用返回*SearchResult的SearchInfo。 - ⚙️ 平台与锁文件:CI 部署常需
--no-dev+ 优化 autoload 的组合,除了布尔参数,也可用InstallWithOptions传--classmap-authoritative、InstallWithAPcu等开关做更细的部署调优。