⚡ 便捷方法
一组高层封装,把「判断项目状态」「读 composer.json/lock」「列已装包/直接依赖」「按类型/废弃筛选」「命名空间/脚本查询」「目录定位」等常用操作收敛为一行调用。
这些方法大多直接读文件或组合多个 composer 子命令,避免你手写解析逻辑。它们分三类:🩺 状态判断、📊 项目摘要、🔍 目录与配置查询。
何时使用
- 🩺 启动时快速判断当前目录是否 Composer 项目、是否已 install。
- 📊 生成项目体检报告:依赖数、过时包数、漏洞数、Composer/PHP 版本——一条
GetProjectSummary搞定。 - 📋 列出已装包名或直接依赖名,用于依赖分析脚本。
- 🎯 按类型筛包(找出所有
composer-plugin)或找出已废弃包。 - 🗂️ 拿到 vendor/bin/cache/home 目录路径,规划缓存或产物。
结构化类型
ProjectSummary
GetProjectSummary 返回,聚合多源信息的项目体检报告。
type ProjectSummary struct {
Name string `json:"name,omitempty"`
Description string `json:"description,omitempty"`
Type string `json:"type,omitempty"`
License string `json:"license,omitempty"`
DirectDependencyCount int `json:"direct_dependency_count"`
DevDependencyCount int `json:"dev_dependency_count"`
TotalInstalledCount int `json:"total_installed_count"`
OutdatedCount int `json:"outdated_count"`
VulnerabilityCount int `json:"vulnerability_count"`
ComposerVersion string `json:"composer_version,omitempty"`
PHPVersion string `json:"php_version,omitempty"`
}ProjectDependencies
GetProjectDependencies 返回,依赖计数与包名列表。
type ProjectDependencies struct {
DirectCount int `json:"direct_count"`
DevCount int `json:"dev_count"`
TotalInstalled int `json:"total_installed"`
DirectPackages []string `json:"direct_packages,omitempty"`
DevPackages []string `json:"dev_packages,omitempty"`
InstalledPackages []string `json:"installed_packages,omitempty"`
}方法签名
🩺 状态判断
| 方法 | 签名 | 说明 |
|---|---|---|
| 📦 IsProject | func (c *Composer) IsProject() bool | 当前工作目录是否有 composer.json |
| 📂 IsProjectIn | func (c *Composer) IsProjectIn(dir string) bool | 指定目录是否有 composer.json |
| 🔒 HasComposerLock | func (c *Composer) HasComposerLock() bool | 是否存在 composer.lock |
| 📁 HasVendorDir | func (c *Composer) HasVendorDir() bool | 是否存在 vendor 目录 |
| ✅ IsPackageInstalled | func (c *Composer) IsPackageInstalled(packageName string) bool | 包是否已安装 |
| 🧪 IsPackageDev | func (c *Composer) IsPackageDev(packageName string) (bool, error) | 包是否在 require-dev |
📊 项目摘要与依赖
| 方法 | 签名 | 说明 |
|---|---|---|
| 📋 GetInstalledPackageNames | func (c *Composer) GetInstalledPackageNames() ([]string, error) | 所有已装包名 |
| 🎯 GetDirectDependencyNames | func (c *Composer) GetDirectDependencyNames() ([]string, error) | 直接依赖包名 |
| 🔢 GetPackageVersionsList | func (c *Composer) GetPackageVersionsList(packageName string) ([]string, error) | 某包所有可用版本 |
| 📊 GetProjectDependencies | func (c *Composer) GetProjectDependencies() (*ProjectDependencies, error) | 依赖摘要 |
| 📈 GetProjectSummary | func (c *Composer) GetProjectSummary() (*ProjectSummary, error) | 项目体检报告 |
| 🔖 GetRequireWithVersion | func (c *Composer) GetRequireWithVersion(packageName string) (string, error) | 包的已装版本号 |
| 🏷️ GetPackagesByType | func (c *Composer) GetPackagesByType(packageType string) ([]string, error) | 按类型筛包 |
| ⚠️ GetAbandonedPackagesFromLock | func (c *Composer) GetAbandonedPackagesFromLock() ([]string, error) | 从 lock 找废弃包 |
| 🗺️ GetNamespaceMap | func (c *Composer) GetNamespaceMap() (map[string]string, error) | PSR-4 命名空间→目录映射 |
| 📜 GetScripts | func (c *Composer) GetScripts() (map[string]interface{}, error) | composer.json 脚本 |
🗂️ 目录与文件读取
| 方法 | 签名 | 说明 |
|---|---|---|
| 🏠 GetComposerHomeDir | func (c *Composer) GetComposerHomeDir() (string, error) | composer config home |
| 💾 GetCacheDir | func (c *Composer) GetCacheDir() (string, error) | composer config cache-dir |
| 📦 GetVendorDir | func (c *Composer) GetVendorDir() (string, error) | vendor 目录(带回退默认值) |
| 🗂️ GetBinDir | func (c *Composer) GetBinDir() (string, error) | bin 目录(带回退默认值) |
🔧 包级解析函数
| 方法 | 签名 | 说明 |
|---|---|---|
| 📋 ParsePackageList | func ParsePackageList(output string) []string | 解析 composer show 文本输出 |
| 🔢 ParsePackageVersions | func ParsePackageVersions(output string) ([]string, error) | 解析 show --all --format=json 版本 |
示例
项目体检报告
package main
import (
"fmt"
"log"
"github.com/scagogogo/composer-skills/pkg/composer"
)
func main() {
comp, err := composer.New(composer.DefaultOptions())
if err != nil {
log.Fatal(err)
}
summary, err := comp.GetProjectSummary()
if err != nil {
log.Fatal(err)
}
fmt.Printf("📦 %s (%s)\n", summary.Name, summary.Type)
fmt.Printf(" 直接依赖 %d / 开发依赖 %d / 已安装 %d\n",
summary.DirectDependencyCount, summary.DevDependencyCount, summary.TotalInstalledCount)
fmt.Printf(" 过时 %d / 漏洞 %d\n", summary.OutdatedCount, summary.VulnerabilityCount)
fmt.Printf(" Composer %s / PHP %s\n", summary.ComposerVersion, summary.PHPVersion)
}列出所有已装包名
pkgs, err := comp.GetInstalledPackageNames()
if err != nil {
log.Fatal(err)
}
for _, p := range pkgs {
fmt.Println(p)
}按类型筛包
plugins, err := comp.GetPackagesByType("composer-plugin")
if err != nil {
log.Fatal(err)
}
for _, p := range plugins {
fmt.Println("🔌", p)
}找出已废弃包
abandoned, err := comp.GetAbandonedPackagesFromLock()
if err != nil {
log.Fatal(err)
}
if len(abandoned) > 0 {
fmt.Println("⚠️ 以下包已废弃,建议替换:")
for _, p := range abandoned {
fmt.Println(" -", p)
}
}查某包已装版本
v, err := comp.GetRequireWithVersion("symfony/console")
if err != nil {
log.Fatal(err)
}
fmt.Println("symfony/console 版本:", v)判断项目状态
if !comp.IsProject() {
log.Fatal("当前目录不是 Composer 项目")
}
if !comp.HasComposerLock() {
fmt.Println("⚠️ 缺少 composer.lock,建议执行 composer install")
}
if !comp.HasVendorDir() {
fmt.Println("⚠️ 缺少 vendor 目录,依赖未安装")
}
if comp.IsPackageInstalled("phpunit/phpunit") {
fmt.Println("✅ 已安装 PHPUnit")
}拿目录路径
home, _ := comp.GetComposerHomeDir()
cache, _ := comp.GetCacheDir()
vendor, _ := comp.GetVendorDir()
bin, _ := comp.GetBinDir()
fmt.Printf("home=%s\ncache=%s\nvendor=%s\nbin=%s\n", home, cache, vendor, bin)解析函数独立使用
// 你可以自己跑 composer show 拿输出,再用 ParsePackageList 提取
output := `symfony/console v5.4.0 Eases...
monolog/monolog 2.5.0 Sends...`
for _, name := range composer.ParsePackageList(output) {
fmt.Println(name)
}进阶
GetProjectSummary 的容错
GetProjectSummary 内部对每个子调用都做了 err == nil 判断——任何一项失败(如无 lock 文件)只会让对应字段留空,不会中断整体报告。这让它适合做「尽力而为」的体检。
两个废弃包方法
GetAbandonedPackagesFromLock(本文件)直接读 composer.lock 的 abandoned 字段,无需执行命令;audit.go 的 GetAbandonedPackages 走 composer audit 命令并返回 []Vulnerability。前者快、后者全(含废弃原因等额外信息)。
GetVendorDir / GetBinDir 的回退
当 composer config vendor-dir 失败(如未初始化项目),它们回退到 <工作目录>/vendor 与 <工作目录>/vendor/bin,不返回错误。这是有意设计,便于在项目未配置时也能拿到合理默认路径。
IsPackageInstalled 的判定
IsPackageInstalled 执行 composer show <pkg>,成功即视为已安装。注意 Composer 在包存在但版本异常时也可能返回非零退出码,此判定是「乐观」的。