📋 包列表
按供应商、类型或附加字段批量获取 Packagist 上的包名列表,以及获取流行包榜单。与 搜索 不同,列表方法返回的是包名集合(不走搜索打分),适合全量遍历、镜像同步、生态统计。
何时使用
- 📋 全量遍历某个 vendor(如
symfony/*下所有包)做依赖梳理。 - 🏷️ 拉取某类
type的所有包(如全部composer-plugin)。 - 🔄 镜像同步:用
ListPackagesWithData一次性拿到包名 + 仓库 URL + 类型。 - 📈 用
ListPopularPackages生成热门包榜单。
数据模型
PackageListResponse
pkg/domain/package_list.go,对应 /packages/list.json(无 fields 时)。
type PackageListResponse struct {
PackageNames []string `json:"packageNames"`
}| 字段 | 类型 | 说明 |
|---|---|---|
PackageNames | []string | 包名列表(vendor/package) |
PackageListWithDataResponse / PackageData
对应 /packages/list.json?fields[]=...,带附加字段。
type PackageListWithDataResponse struct {
Packages map[string]PackageData `json:"package"`
}
type PackageData struct {
Type string `json:"type,omitempty"`
Repository string `json:"repository,omitempty"`
Abandoned interface{} `json:"abandoned,omitempty"`
}| 字段 | 类型 | 说明 |
|---|---|---|
Packages | map[string]PackageData | 键为包名,值为附加数据 |
PackageData.Type | string | 包类型(需在 fields 中请求 type) |
PackageData.Repository | string | 仓库 URL(需请求 repository) |
PackageData.Abandoned | interface{} | 废弃标记:false/true,或字符串(推荐替代包名,需请求 abandoned) |
Abandoned 字段类型
Abandoned 用 interface{} 承载是因为 Packagist 返回值可能是布尔(false/true)也可能是字符串(推荐替代的包名)。使用时需做类型断言。
PopularPackagesResponse / PopularPackage
pkg/domain/popular_packages.go,对应 /explore/popular.json。
type PopularPackagesResponse struct {
Packages []PopularPackage `json:"packages"`
Total int `json:"total"`
Next string `json:"next,omitempty"`
}
type PopularPackage struct {
Name string `json:"name"`
Description string `json:"description"`
URL string `json:"url"`
Downloads int `json:"downloads"`
Favers int `json:"favers"`
}| 字段 | 类型 | 说明 |
|---|---|---|
Packages | []PopularPackage | 当前页流行包列表 |
Total | int | 流行包总数 |
Next | string | 下一页 URL(无则空) |
PopularPackage.Name | string | 包名 |
PopularPackage.Description | string | 描述 |
PopularPackage.URL | string | Packagist 页面 URL |
PopularPackage.Downloads | int | 下载次数 |
PopularPackage.Favers | int | 收藏数 |
ListPackages
📋 获取所有包名列表。对应 GET https://packagist.org/packages/list.json。
签名
func (c *ComposerClient) ListPackages() (*domain.PackageListResponse, error)参数
无。
返回值
| 值 | 类型 | 说明 |
|---|---|---|
| 结果 | *domain.PackageListResponse | 含全量 PackageNames |
| 错误 | error | HTTP 失败、非 200、JSON 解析失败时返回 |
示例
package main
import (
"fmt"
"log"
"time"
"github.com/scagogogo/composer-skills/pkg/client"
)
func main() {
c := client.NewComposerClient(120 * time.Second) // 全量列表较大,超时给足
list, err := c.ListPackages()
if err != nil {
log.Fatalf("获取包列表失败: %v", err)
}
fmt.Printf("Packagist 共有 %d 个包\n", len(list.PackageNames))
for i, name := range list.PackageNames {
if i >= 5 {
break
}
fmt.Println(" -", name)
}
}响应体很大
/packages/list.json 返回全量包名(数十万条,响应体几十 MB)。生产环境建议超时设到 120s 以上,或改用底层 Repository.List 配合代理;需要落盘则用 DownloadIndexToFile。
ListPackagesByVendor
📋 获取指定供应商(vendor)下的所有包名。对应 GET https://packagist.org/packages/list.json?vendor={vendor}。
签名
func (c *ComposerClient) ListPackagesByVendor(vendor string) (*domain.PackageListResponse, error)参数
| 参数 | 类型 | 说明 |
|---|---|---|
vendor | string | 供应商名,如 symfony、laravel |
返回值
| 值 | 类型 | 说明 |
|---|---|---|
| 结果 | *domain.PackageListResponse | 该 vendor 下的包名列表 |
| 错误 | error | HTTP 失败、非 200、JSON 解析失败时返回 |
示例
list, err := c.ListPackagesByVendor("symfony")
if err != nil {
log.Fatal(err)
}
fmt.Printf("symfony/* 下共 %d 个包\n", len(list.PackageNames))
for _, name := range list.PackageNames {
fmt.Println(name)
}vendor 与 package 名
Packagist 包名格式为 vendor/package,vendor 是斜杠前的部分。vendor=symfony 会返回所有 symfony/* 包。
ListPackagesByType
📋 获取指定类型的所有包名。对应 GET https://packagist.org/packages/list.json?type={type}。
签名
func (c *ComposerClient) ListPackagesByType(packageType string) (*domain.PackageListResponse, error)参数
| 参数 | 类型 | 说明 |
|---|---|---|
packageType | string | 包类型,如 library、composer-plugin、project、metapackage |
返回值
| 值 | 类型 | 说明 |
|---|---|---|
| 结果 | *domain.PackageListResponse | 该类型的包名列表 |
| 错误 | error | HTTP 失败、非 200、JSON 解析失败时返回 |
示例
list, err := c.ListPackagesByType("composer-plugin")
if err != nil {
log.Fatal(err)
}
fmt.Printf("composer-plugin 类型共 %d 个包\n", len(list.PackageNames))ListPackagesWithData
📋 获取包列表,并附带额外字段(仓库 URL、类型、废弃标记)。对应 GET https://packagist.org/packages/list.json?fields[]={field}。
签名
func (c *ComposerClient) ListPackagesWithData(fields []string) (*domain.PackageListWithDataResponse, error)参数
| 参数 | 类型 | 说明 |
|---|---|---|
fields | []string | 要返回的附加字段名列表,每个作为 fields[] 查询参数发出 |
可选字段值(参考 Packagist 文档):
| 字段 | 说明 |
|---|---|
repository | 仓库 URL |
type | 包类型 |
abandoned | 废弃标记(布尔或推荐替代包名) |
返回值
| 值 | 类型 | 说明 |
|---|---|---|
| 结果 | *domain.PackageListWithDataResponse | 包名 → 附加数据映射 |
| 错误 | error | HTTP 失败、非 200、JSON 解析失败时返回 |
示例
resp, err := c.ListPackagesWithData([]string{"repository", "type", "abandoned"})
if err != nil {
log.Fatal(err)
}
for name, data := range resp.Packages {
fmt.Printf("%s\n", name)
fmt.Printf(" 类型: %s\n", data.Type)
fmt.Printf(" 仓库: %s\n", data.Repository)
if data.Abandoned != nil && data.Abandoned != false {
fmt.Printf(" ⚠ 已废弃: %v\n", data.Abandoned)
}
}字段选择
请求越多 fields,响应体越大。只取需要的字段。注意:不带 fields 时端点返回的是 packageNames 数组(PackageListResponse),带 fields 时返回的是 package 映射(PackageListWithDataResponse)——两种响应结构不同,SDK 用不同类型解析。
ListPopularPackages
📋 获取流行包榜单。对应 GET https://packagist.org/explore/popular.json?per_page={n}。
签名
func (c *ComposerClient) ListPopularPackages(perPage int) (*domain.PopularPackagesResponse, error)参数
| 参数 | 类型 | 说明 |
|---|---|---|
perPage | int | 每页条数,直接拼为 per_page 查询参数 |
返回值
| 值 | 类型 | 说明 |
|---|---|---|
| 结果 | *domain.PopularPackagesResponse | 含 Packages、Total、Next |
| 错误 | error | HTTP 失败、非 200、JSON 解析失败时返回 |
示例
res, err := c.ListPopularPackages(100)
if err != nil {
log.Fatal(err)
}
fmt.Printf("流行包共 %d 个,当前页 %d 个\n", res.Total, len(res.Packages))
for i, p := range res.Packages {
fmt.Printf("%2d. %s (下载 %d, 收藏 %d)\n", i+1, p.Name, p.Downloads, p.Favers)
}进阶
五个列表方法对比
| 方法 | 返回 | 维度 | 适用 |
|---|---|---|---|
ListPackages | 包名数组 | 全量 | 全量遍历 |
ListPackagesByVendor | 包名数组 | 按 vendor | 厂商维度梳理 |
ListPackagesByType | 包名数组 | 按 type | 类型维度梳理 |
ListPackagesWithData | 包名 → 附加字段 | 全量 + 字段 | 镜像同步(带仓库 URL) |
ListPopularPackages | 流行包详情 | 榜单 | 热门包展示 |
与搜索的区别
搜索方法 走 /search.json,按相关性打分并分页;列表方法走 /packages/list.json,返回的是无序包名集合,不分页(除 ListPopularPackages)。要全量数据用列表,要「按关键词找最相关的」用搜索。
🔗 相关
- 🏗️ 全量列表底层见 Repository.List 与 DownloadIndexToFile。
- 📦 拿到包名后查详情见 GetPackage。