Skip to content

📦 cli_package_management — 包管理

该示例演示如何用 Composer Skills SDK 在本地 PHP 项目中执行依赖包的全生命周期管理:安装、更新、添加、移除与搜索。

示例定位

cli_package_management 是 Composer CLI 系列示例中的「依赖管理」核心篇。它把日常 composer install / update / require / remove / search 全部映射到 Go SDK 调用,让你能在 Go 程序里以代码方式操控 composer.jsonvendor/ 目录,而无需手动拼命令行或 shell out。

学完本示例,你将掌握:

  • 📥 依赖安装的三种姿势(含 dev、排除 dev、优化 autoload)
  • 🔄 全量更新与按包名定向更新
  • ➕ 添加普通依赖、指定版本依赖、开发依赖
  • ➖ 移除普通依赖与开发依赖
  • 🔍 关键字搜索包并解析原始输出
  • 🛠️ 自动加载配置的转储与优化(dump-autoload

对应 SDK 方法全部位于 pkg/composer 包,集中在 dependencies.gopackages.go 两个文件。

完整代码

下面汇总目录下三个示例文件的关键逻辑(已精简重复的日志输出,保留完整调用链)。

01_install_update.go — 安装与更新

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 — 添加与移除

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 — 搜索包

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-dev
  • noDev=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 做了轻量解析,提取首字段作为包名。需要更结构化的结果时,可改用 SearchOnlyNameSearchWithType 或返回结构化 *SearchResultSearchInfo

运行方式

需要本地环境

本系列示例执行本地 composer 二进制,需要本机已安装 PHP 7.4+ 与 Composer 2.0+。若未安装,SDK 的自动安装能力会兜底。示例中的 projectDir 需改成你本机真实存在的 PHP 项目路径。

bash
# 克隆仓库
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.jsonvendor/,建议先在一个用 composer init 新建的空项目里演练,避免污染生产代码库。

涉及的 SDK 方法

方法名所属包文档链接
Newpkg/composer/sdk/composer/methods/new
SetWorkingDirpkg/composer/sdk/composer/methods/set-working-dir
Installpkg/composer/sdk/composer/methods/install
Updatepkg/composer/sdk/composer/methods/update
DumpAutoloadpkg/composer/sdk/composer/methods/dump-autoload
RequirePackagepkg/composer/sdk/composer/methods/require-package
Removepkg/composer/sdk/composer/methods/remove
RequirePackageWithOptionspkg/composer/sdk/composer/methods/require-package-with-options
Searchpkg/composer/sdk/composer/methods/search

进阶

基于 MIT 许可证发布