Skip to content

🔍 包操作

本页讲解 pkg/composer 中针对单个/多个包的操作方法,定义在 packages.goadditional_methods.goresult_types.go。它们对应 composer 的 requireremoveshowsearchdependswhywhy-notoutdatedbumpreinstallbrowse 等子命令。

🎯 何时使用

  • ➕ 给项目添加一个新依赖 → RequirePackage
  • ➖ 移除不再需要的依赖 → Remove
  • 🔎 查看某个已装包的版本/依赖/源码位置 → ShowPackage 或结构化 ShowPackageInfo
  • 🌐 在 Packagist 上找包 → Search 或结构化 SearchInfo
  • 🌳 理解包与包之间的依赖关系 → ShowDependencyTree / WhyPackage / ShowReverseDependencies
  • ⬆️ 找出哪些包可以升级 → OutdatedPackages 或结构化 GetOutdatedInfo
  • 🚫 排查为什么装不上某个版本 → WhyNotPackage

📋 方法总览

方法签名概要等价命令
RequirePackageRequirePackage(packageName, version string, dev bool) errorcomposer require [--dev] pkg:ver
RequirePackageWithOptionsRequirePackageWithOptions(packageName, version string, options map[string]string) errorcomposer require [options] pkg:ver
RequireMultipleRequireMultiple(packages map[string]string, dev bool) errorcomposer require [--dev] pkg1:ver1 pkg2:ver2 ...
🧪 RequireDryRunRequireDryRun(packageName, version string) (string, error)composer require --dry-run pkg:ver
RemoveRemove(packageName string, dev bool) errorcomposer remove [--dev] pkg
RemoveWithOptionsRemoveWithOptions(packageName string, options map[string]string) errorcomposer remove [options] pkg
RemoveMultipleRemoveMultiple(packages []string, dev bool) errorcomposer remove [--dev] pkg1 pkg2 ...
🧪 RemoveDryRunRemoveDryRun(packageName string) (string, error)composer remove --dry-run pkg
🔎 ShowPackageShowPackage(packageName string) (string, error)composer show pkg
ShowPackageWithFormatShowPackageWithFormat(packageName, format string) (string, error)composer show pkg --format=FMT
ShowPackageInfoShowPackageInfo(packageName string) (*PackageInfo, error)composer show pkg --format=json(结构化)
ShowAllPackagesShowAllPackages() (string, error)composer show
ShowDirectPackagesShowDirectPackages() (string, error)composer show --direct
ShowSelfPackageShowSelfPackage() (string, error)composer show --self
ShowLatestVersionsShowLatestVersions() (string, error)composer show --latest
ShowWithOptionsShowWithOptions(options map[string]string) (string, error)composer show [options]
🌳 ShowDependencyTreeShowDependencyTree(packageName string) (string, error)composer show --tree [pkg]
🔗 ShowReverseDependenciesShowReverseDependencies(packageName string) (string, error)composer depends pkg
DependsWithOptionsDependsWithOptions(packageName string, options map[string]string) (string, error)composer depends pkg [options]
WhyPackageWhyPackage(packageName string) (string, error)composer why pkg
WhyWithOptionsWhyWithOptions(packageName string, options map[string]string) (string, error)composer why pkg [options]
🚫 WhyNotPackageWhyNotPackage(packageName, version string) (string, error)composer why-not pkg ver
WhyNotWithOptionsWhyNotWithOptions(packageName, version string, options map[string]string) (string, error)composer why-not pkg ver [options]
⬆️ OutdatedPackagesOutdatedPackages() (string, error)composer outdated
OutdatedPackagesDirectOutdatedPackagesDirect() (string, error)composer outdated --direct
OutdatedWithOptionsOutdatedWithOptions(options map[string]string) (string, error)composer outdated [options]
OutdatedWithFormatOutdatedWithFormat(format string) (string, error)composer outdated --format=FMT
ShowOutdatedWithFormatShowOutdatedWithFormat(format string) (string, error)composer outdated --format=FMT(别名)
ShowOutdatedMinorOnlyShowOutdatedMinorOnly() (string, error)composer outdated --minor-only
GetOutdatedInfoGetOutdatedInfo() (*OutdatedResult, error)composer outdated --format=json(结构化)
GetOutdatedInfoWithOptionsGetOutdatedInfoWithOptions(options map[string]string) (*OutdatedResult, error)同上 + 选项
🌐 SearchSearch(query string) (string, error)composer search query
SearchWithFormatSearchWithFormat(query, format string) (string, error)composer search query --format=FMT
SearchOnlyNameSearchOnlyName(query string) (string, error)composer search query --only-name
SearchWithTypeSearchWithType(query, packageType string) (string, error)composer search query --type=TYPE
SearchInfoSearchInfo(query string) (*SearchResult, error)composer search query --format=json(结构化)
📈 BumpPackagesBumpPackages(packages []string) errorcomposer bump [packages...]
BumpPackagesWithOptionsBumpPackagesWithOptions(packages []string, options map[string]string) errorcomposer bump [options] [packages...]
🔁 ReinstallReinstall(packageName string) errorcomposer reinstall pkg
ReinstallWithOptionsReinstallWithOptions(packageName string, options map[string]string) errorcomposer reinstall [options] pkg
ReinstallMultipleReinstallMultiple(packages []string) errorcomposer reinstall pkg1 pkg2 ...
ReinstallMultipleWithOptionsReinstallMultipleWithOptions(packages []string, options map[string]string) errorcomposer reinstall [options] pkg1 ...
🌍 BrowsePackageBrowsePackage(packageName string) errorcomposer browse pkg
BrowsePackageWithOptionsBrowsePackageWithOptions(packageName string, options map[string]string) errorcomposer browse pkg [options]

✨ 标记的方法返回结构化 Go 类型而非原始字符串,详见下方"结构化返回值"章节。


RequirePackage

向项目添加一个新的依赖包,并写入 composer.json 后立即安装。

签名

go
func (c *Composer) RequirePackage(packageName string, version string, dev bool) error

参数

参数类型说明
packageNamestring包名,例如 "symfony/console"
versionstring版本约束,例如 "^5.0";为空则用最新版本
devbooltrue 则作为开发依赖(--dev

返回值

类型说明
error失败时返回包裹了 ErrRequirePackageFailed 的错误

示例

go
// 添加生产依赖
err := comp.RequirePackage("symfony/console", "^5.0", false)
if err != nil {
    log.Fatalf("添加依赖失败: %v", err)
}

// 添加开发依赖
err = comp.RequirePackage("phpunit/phpunit", "^9.0", true)

进阶

  • 想加多个包一次性用 RequireMultiple(map[string]string{"symfony/console": "^5.0", "monolog/monolog": "^2.0"}, false)
  • 想预演而不真正改 composer.jsonRequireDryRun(packageName, version)
  • 需要更多选项(如 --prefer-source--no-update)用 RequirePackageWithOptions

Remove

从项目中移除指定的依赖包。

签名

go
func (c *Composer) Remove(packageName string, dev bool) error

参数

参数类型说明
packageNamestring要移除的包名
devbooltrue 则从开发依赖中移除(--dev

示例

go
// 移除生产依赖
err := comp.Remove("symfony/console", false)

// 移除开发依赖
err = comp.Remove("phpunit/phpunit", true)

进阶

  • 批量移除用 RemoveMultiple([]string{"a/b", "c/d"}, false)
  • 预演用 RemoveDryRun(packageName)

🔎 ShowPackage / ✨ ShowPackageInfo

显示指定包的详细信息(版本、依赖、安装位置等)。

签名

go
func (c *Composer) ShowPackage(packageName string) (string, error)
func (c *Composer) ShowPackageInfo(packageName string) (*PackageInfo, error)

参数

参数类型说明
packageNamestring要显示信息的包名

返回值

  • ShowPackage(string, error) — composer 原始文本输出,失败时返回 ErrShowPackageFailed
  • ShowPackageInfo(*PackageInfo, error) — 解析后的结构体(内部执行 composer show pkg --format=json)。

示例

go
// 原始文本
output, err := comp.ShowPackage("symfony/console")
fmt.Println(output)

// 结构化
info, err := comp.ShowPackageInfo("symfony/console")
if err != nil {
    log.Fatalf("获取包信息失败: %v", err)
}
fmt.Printf("包 %s 版本 %s\n", info.Name, info.Version)
fmt.Printf("类型: %s, 主页: %s\n", info.Type, info.Homepage)
fmt.Printf("许可证: %v\n", info.License)

进阶

  • 想以自定义格式(非 json)输出用 ShowPackageWithFormat(packageName, format)
  • 查看所有已装包用 ShowAllPackages();只看直接依赖用 ShowDirectPackages()

🌐 Search / ✨ SearchInfo

在 Packagist 上搜索符合关键词的包。

签名

go
func (c *Composer) Search(query string) (string, error)
func (c *Composer) SearchInfo(query string) (*SearchResult, error)

参数

参数类型说明
querystring搜索关键词

返回值

  • Search(string, error) — 原始文本,失败时返回 ErrSearchFailed
  • SearchInfo(*SearchResult, error) — 结构化结果(内部执行 composer search query --format=json)。

示例

go
// 结构化搜索
res, err := comp.SearchInfo("logger")
if err != nil {
    log.Fatalf("搜索失败: %v", err)
}
for _, r := range res.Results {
    fmt.Printf("%s: %s\n", r.Name, r.Description)
}

进阶

  • 只按名称精确匹配用 SearchOnlyName(query),可减少描述带来的噪音。
  • 按类型筛选用 SearchWithType(query, "composer-plugin"),支持 library/composer-plugin/project 等类型。
  • 自定义输出格式用 SearchWithFormat(query, "json")

⬆️ OutdatedPackages / ✨ GetOutdatedInfo

显示项目中所有过时的包及可用更新。

签名

go
func (c *Composer) OutdatedPackages() (string, error)
func (c *Composer) GetOutdatedInfo() (*OutdatedResult, error)
func (c *Composer) GetOutdatedInfoWithOptions(options map[string]string) (*OutdatedResult, error)

返回值

  • OutdatedPackages(string, error) — 原始文本。
  • GetOutdatedInfo(*OutdatedResult, error) — 结构化结果(内部执行 composer outdated --format=json)。

示例

go
// 结构化查询过时包
outdated, err := comp.GetOutdatedInfo()
if err != nil {
    log.Fatalf("获取过时包信息失败: %v", err)
}
for _, p := range outdated.Installed {
    fmt.Printf("⬆️  %s: %s -> %s (%s)\n",
        p.Name, p.Installed, p.Latest, p.LatestStatus)
}
fmt.Printf("共 %d 个过时包\n", outdated.Count)

进阶

  • 只看直接依赖用 OutdatedPackagesDirect()
  • 只看 minor 版本更新用 ShowOutdatedMinorOnly()
  • 自定义选项用 OutdatedWithOptions(map[string]string{"direct": "", "minor-only": ""})GetOutdatedInfoWithOptions
  • 自定义格式用 OutdatedWithFormat("json") / ShowOutdatedWithFormat("text")

关于退出码

composer outdated 在有过时包时可能返回非零退出码,但输出仍包含有效 JSON。GetOutdatedInfo 已处理此情况:当 err != niloutput == "" 时返回空结果而非错误。


🌳 ShowDependencyTree

以树形结构显示包的依赖关系。

签名

go
func (c *Composer) ShowDependencyTree(packageName string) (string, error)

参数

参数类型说明
packageNamestring包名;为空串则显示整个项目的依赖树

示例

go
// 整个项目的依赖树
output, err := comp.ShowDependencyTree("")

// 特定包的依赖树
output, err = comp.ShowDependencyTree("symfony/console")

进阶

  • 想把树解析成 Go 结构体,用 parsing.go 中的 ParseDependencyTreeJSON(output),返回 []DependencyNode,每个节点有 NameVersionChildren

WhyPackage / 🚫 WhyNotPackage / 🔗 ShowReverseDependencies

这三组方法用于理解依赖关系:

方法签名等价命令用途
WhyPackageWhyPackage(packageName string) (string, error)composer why pkg解释为什么安装了某包(被谁依赖)
WhyNotPackageWhyNotPackage(packageName, version string) (string, error)composer why-not pkg ver解释为什么不能装某版本(冲突来源)
ShowReverseDependenciesShowReverseDependencies(packageName string) (string, error)composer depends pkg显示哪些已装包依赖于此包

示例

go
// 为什么会安装 polyfill-mbstring?
why, _ := comp.WhyPackage("symfony/polyfill-mbstring")
fmt.Println("安装原因:", why)

// 为什么装不上 symfony/console v4.0.0?
whyNot, _ := comp.WhyNotPackage("symfony/console", "v4.0.0")
fmt.Println("无法安装的原因:", whyNot)

// 谁依赖了 polyfill-mbstring?
deps, _ := comp.ShowReverseDependencies("symfony/polyfill-mbstring")
fmt.Println("反向依赖:", deps)

进阶

  • 三个方法都有 WithOptions 变体:WhyWithOptionsWhyNotWithOptionsDependsWithOptions,可传 map[string]string{"format": "json"} 等选项。

📈 BumpPackages

将指定包升级到符合 composer.json 中版本约束的最新版本(不改约束,只更新 lock 中的版本)。需要 Composer 2.4+。

签名

go
func (c *Composer) BumpPackages(packages []string) error
func (c *Composer) BumpPackagesWithOptions(packages []string, options map[string]string) error

参数

参数类型说明
packages[]string要升级的包名列表;为空切片则升级所有包

示例

go
// 升级多个包
err := comp.BumpPackages([]string{"symfony/console", "symfony/process"})
if err != nil {
    log.Fatalf("升级包失败: %v", err)
}

// 升级所有包
err = comp.BumpPackages([]string{})

// 带选项(仅开发依赖 + 干跑预演)
options := map[string]string{
    "dev-only":      "",
    "prefer-stable": "",
    "dry-run":       "",
}
err = comp.BumpPackagesWithOptions([]string{"symfony/console"}, options)

🔁 Reinstall

重新安装指定的包,使用 Composer 2.2+ 的原生 reinstall 命令。

签名

go
func (c *Composer) Reinstall(packageName string) error
func (c *Composer) ReinstallWithOptions(packageName string, options map[string]string) error
func (c *Composer) ReinstallMultiple(packages []string) error
func (c *Composer) ReinstallMultipleWithOptions(packages []string, options map[string]string) error

示例

go
// 重新安装单个包
err := comp.Reinstall("symfony/console")

// 用 prefer-source 重新安装
err = comp.ReinstallWithOptions("symfony/console", map[string]string{"prefer-source": ""})

// 批量重新安装
err = comp.ReinstallMultiple([]string{"symfony/console", "symfony/process"})

版本要求

reinstall 命令需要 Composer 2.2 或更高版本。旧版本请用 Remove + RequirePackage 组合替代。


🌍 BrowsePackage

用默认浏览器打开指定包的项目页面(通常是 GitHub 仓库)。

签名

go
func (c *Composer) BrowsePackage(packageName string) error
func (c *Composer) BrowsePackageWithOptions(packageName string, options map[string]string) error

示例

go
// 打开包主页
err := comp.BrowsePackage("symfony/console")

// 打开文档页面
err = comp.BrowsePackageWithOptions("symfony/console", map[string]string{"docs": ""})

// 打开问题跟踪页面
err = comp.BrowsePackageWithOptions("symfony/console", map[string]string{"issues": ""})

环境依赖

需要操作系统支持打开浏览器,且包在 composer.json 中声明了项目 URL。无图形界面的服务器环境通常不适用。


🧱 结构化返回值

包操作的结构化方法返回以下类型(均定义在 result_types.go):

PackageInfoShowPackageInfo 返回)

go
type PackageInfo struct {
    Name        string                 `json:"name"`
    Version     string                 `json:"version"`
    Description string                 `json:"description,omitempty"`
    Type        string                 `json:"type,omitempty"`
    Keywords    []string               `json:"keywords,omitempty"`
    Homepage    string                 `json:"homepage,omitempty"`
    License     []string               `json:"license,omitempty"`
    Authors     []PackageAuthor        `json:"authors,omitempty"`
    Support     map[string]string      `json:"support,omitempty"`
    Require     map[string]string      `json:"require,omitempty"`
    RequireDev  map[string]string      `json:"require_dev,omitempty"`
    Autoload    map[string]interface{} `json:"autoload,omitempty"`
    Source      PackageSource          `json:"source,omitempty"`
    Dist        PackageDist            `json:"dist,omitempty"`
    Abandoned   interface{}            `json:"abandoned,omitempty"` // bool 或 string
    Time        string                 `json:"time,omitempty"`
}

OutdatedResultGetOutdatedInfo 返回)

go
type OutdatedResult struct {
    Installed []OutdatedPackage `json:"installed"`
    Count     int               `json:"count,omitempty"`
}

type OutdatedPackage struct {
    Name         string      `json:"name"`
    Latest       string      `json:"latest"`
    Installed    string      `json:"version"`
    LatestStatus string      `json:"latest_status"` // "semver-safe-update" | "update-possible" | "up-to-date"
    Abandoned    interface{} `json:"abandoned,omitempty"`
}

SearchResultSearchInfo 返回)

go
type SearchResult struct {
    Results []SearchResultItem `json:"results"`
    Total   int                `json:"total,omitempty"`
}

type SearchResultItem struct {
    Name        string `json:"name"`
    Description string `json:"description,omitempty"`
    URL         string `json:"url,omitempty"`
    Repository  string `json:"repository,omitempty"`
}

何时用结构化变体

需要在程序中判断版本号、统计过时包数量、把搜索结果存库或渲染到 UI 时,务必ShowPackageInfo / GetOutdatedInfo / SearchInfo。原始字符串方法只适合人工阅读或日志输出。

🧭 下一步

  • 📦 依赖管理Install / Update / DumpAutoload
  • 🛠️ 核心运行Run / RunWithContext
  • 🧩 便捷查询IsPackageInstalled / GetDirectDependencyNames 等更高层封装

基于 MIT 许可证发布