🔍 Search
Search packages on Packagist by keyword, tags, or type. Three search methods share the same return structure SearchResponse, differing only in query parameters.
When to Use
- 🔍 User inputs keyword, you want to display matching Packagist packages in UI.
- 🧩 Find similar libraries by
tags(e.g., all logging libraries withpsr-3tag). - 🏷️ Filter by
type(e.g., only viewcomposer-plugintype packages). - 📊 Paginate search results for batch analysis.
Data Models
SearchResponse
pkg/domain/search.go, corresponds to https://packagist.org/search.json response.
type SearchResponse struct {
Results []SearchResult `json:"results"`
Total int `json:"total"`
Next string `json:"next,omitempty"`
}| Field | Type | Description |
|---|---|---|
Results | []SearchResult | Current page search results list |
Total | int | Total results matching criteria |
Next | string | Next page URL (empty when no next page) |
SearchResult
type SearchResult struct {
Name string `json:"name"`
Description string `json:"description"`
URL string `json:"url"`
Repository string `json:"repository"`
Downloads int `json:"downloads"`
Favers int `json:"favers"`
}| Field | Type | Description |
|---|---|---|
Name | string | Package name (vendor/package) |
Description | string | Package description |
URL | string | Package page URL on Packagist |
Repository | string | Source code repository URL |
Downloads | int | Download count |
Favers | int | Favorites count |
SearchPackages
🔍 Search packages by keyword. Corresponds to GET https://packagist.org/search.json?q={query}.
Signature
func (c *ComposerClient) SearchPackages(query string, perPage, page int) (*domain.SearchResponse, error)Parameters
| Parameter | Type | Description |
|---|---|---|
query | string | Search keyword |
perPage | int | Items per page; pass 0 or negative means don't send this parameter, Packagist uses default |
page | int | Page number (starting from 1); pass 0 or negative means don't send this parameter |
Return Values
| Value | Type | Description |
|---|---|---|
| Result | *domain.SearchResponse | Search results, contains current page Results, total Total, Next link |
| Error | error | Returned on HTTP failure, non-200, or JSON parsing failure |
Example
package main
import (
"fmt"
"log"
"time"
"github.com/scagogogo/composer-skills/pkg/client"
)
func main() {
c := client.NewComposerClient(30 * time.Second)
res, err := c.SearchPackages("logger", 15, 1)
if err != nil {
log.Fatalf("Search failed: %v", err)
}
fmt.Printf("Total %d results\n", res.Total)
for _, r := range res.Results {
fmt.Printf("- %s : %s (downloads %d, favorites %d)\n",
r.Name, r.Description, r.Downloads, r.Favers)
}
}Pagination
perPage and page are only sent as per_page / page query parameters when greater than 0. Use Next field to page through:
res, _ := c.SearchPackages("logger", 50, 1)
for {
for _, r := range res.Results {
handle(r)
}
if res.Next == "" {
break
}
// Parse Next URL to get page, or directly increment page
page++
res, err = c.SearchPackages("logger", 50, page)
if err != nil {
break
}
}Pagination Parameter Convention
Packagist search defaults 15 items per page. per_page upper limit is about 100, exceeding may be truncated by server. For large batch data, recommend using ListPackages to directly fetch full package names list (no search).
SearchPackagesByTags
🔍 Search packages by tags. Corresponds to GET https://packagist.org/search.json?tags[]={tag}.
Signature
func (c *ComposerClient) SearchPackagesByTags(tags []string, perPage, page int) (*domain.SearchResponse, error)Parameters
| Parameter | Type | Description |
|---|---|---|
tags | []string | Tags list, each tag sent as a tags query parameter (logical AND, results must contain all tags) |
perPage | int | Items per page; <=0 means don't send |
page | int | Page number; <=0 means don't send |
Return Values
| Value | Type | Description |
|---|---|---|
| Result | *domain.SearchResponse | Same as SearchPackages |
| Error | error | Returned on HTTP failure, non-200, or JSON parsing failure |
Example
res, err := c.SearchPackagesByTags([]string{"psr-3", "log"}, 20, 1)
if err != nil {
log.Fatal(err)
}
fmt.Printf("Packages matching tags total %d\n", res.Total)
for _, r := range res.Results {
fmt.Println(r.Name, "-", r.Description)
}Multi-tag Semantics
Each tag is sent as separate tags[] query parameter, Packagist returns packages containing all these tags.
SearchPackagesByType
🔍 Search by keyword and package type simultaneously. Corresponds to GET https://packagist.org/search.json?q={query}&type={type}.
Signature
func (c *ComposerClient) SearchPackagesByType(query, packageType string, perPage, page int) (*domain.SearchResponse, error)Parameters
| Parameter | Type | Description |
|---|---|---|
query | string | Search keyword |
packageType | string | Package type, e.g., library, composer-plugin, project, metapackage |
perPage | int | Items per page; <=0 means don't send |
page | int | Page number; <=0 means don't send |
Return Values
| Value | Type | Description |
|---|---|---|
| Result | *domain.SearchResponse | Same as SearchPackages |
| Error | error | Returned on HTTP failure, non-200, or JSON parsing failure |
Example
// Only view composer-plugin type packages
res, err := c.SearchPackagesByType("installer", "composer-plugin", 20, 1)
if err != nil {
log.Fatal(err)
}
for _, r := range res.Results {
fmt.Println(r.Name, "-", r.Repository)
}Advanced Topics
Differences Between Three Search Methods
| Method | Query Parameter | Use Case |
|---|---|---|
SearchPackages | q | General keyword fuzzy search |
SearchPackagesByTags | tags[] (multiple) | Precise filter by feature tags |
SearchPackagesByType | q + type | Keyword + package type dual dimension |
🔗 Related
- 📋 Want full package names list (no pagination, no search) see Package Listing.
- 📦 After getting package name, view details see GetPackage.