Skip to content

🚀 cli_basic_usage — Composer CLI 基本用法

本示例演示如何创建 Composer 实例,并通过 Run / RunWithContext 执行基础 Composer 命令,同时设置工作目录与环境变量、触发 Composer 自更新。

🎯 示例定位

cli_basic_usageComposer CLI 本地操作 系列的第一个示例(示例总览第 8 个),是所有 cli_* 系列的起点。它把「拿到一个能跑的 Composer 客户端」这件事拆成最小可运行单元。

  • 📚 你将学到:如何用 composer.DefaultOptions() + composer.New() 完成客户端初始化,如何用 Run 执行任意命令、用 RunWithContext 加超时控制,以及如何通过 SetWorkingDir / SetEnv 调整执行环境,最后调用 SelfUpdate 升级 Composer 自身。
  • 🔗 对应 SDK 方法:composer.NewComposer.RunComposer.RunWithContextComposer.SetWorkingDirComposer.SetEnvComposer.SelfUpdate
  • 💡 与 basic_setup 的区别:basic_setup 面向 Packagist 远程 API 客户端;本例面向本地 Composer CLI 子进程,二者分属不同子系统,本例是后续 cli_package_managementcli_project_management 等所有 CLI 示例的前置基础。

💻 完整代码

go
package cli_basic_usage

import (
	"context"
	"fmt"
	"log"
	"time"

	"github.com/scagogogo/composer-skills/pkg/composer"
)

// Example02RunCommands 演示如何运行基本的Composer命令
func Example02RunCommands() {
	// 创建Composer实例
	options := composer.DefaultOptions()
	c, err := composer.New(options)
	if err != nil {
		log.Fatalf("无法创建Composer实例: %v", err)
	}

	// 示例1:使用Run方法执行简单命令
	output, err := c.Run("--version")
	if err != nil {
		log.Fatalf("执行命令失败: %v", err)
	}
	fmt.Printf("Run方法输出: %s\n", output)
	// 输出示例:Run方法输出: Composer version 2.5.7 2023-12-01 11:43:14

	// 示例2:使用带超时的上下文执行命令
	ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
	defer cancel()

	output, err = c.RunWithContext(ctx, "diagnose")
	if err != nil {
		log.Printf("执行带上下文的命令失败: %v", err)
	} else {
		fmt.Println("RunWithContext方法执行成功,输出省略...")
	}

	// 示例3:设置工作目录后执行命令
	c.SetWorkingDir("/path/to/your/project")
	fmt.Printf("已设置工作目录: %s\n", "/path/to/your/project")

	// 示例4:设置环境变量后执行命令
	c.SetEnv([]string{"COMPOSER_MEMORY_LIMIT=2G", "COMPOSER_NO_INTERACTION=1"})
	fmt.Println("已设置环境变量: COMPOSER_MEMORY_LIMIT=2G, COMPOSER_NO_INTERACTION=1")

	// 示例5: 执行更新自身命令
	fmt.Println("执行 self-update 命令...")
	err = c.SelfUpdate()
	if err != nil {
		log.Printf("更新Composer失败: %v", err)
	} else {
		fmt.Println("Composer自更新成功")
	}
}

🧩 代码讲解

  • 🏗️ 初始化客户端composer.DefaultOptions() 给出一组开箱即用的默认配置,再交给 composer.New(options) 构造 *Composer 实例。若本地未检测到 Composer,SDK 会触发自动安装,因此 err 必须检查。
  • 最简执行c.Run("--version") 直接把参数透传给 Composer 子进程,返回合并后的标准输出字符串。这是跑任意「无副作用查询命令」最轻量的入口。
  • ⏱️ 带超时的执行context.WithTimeout(..., 30*time.Second) 派生可取消的 ctx,c.RunWithContext(ctx, "diagnose") 在超时或取消时会杀掉子进程,避免 diagnose 这类耗时命令卡死调用方。defer cancel() 释放上下文资源。
  • 📁 切换工作目录c.SetWorkingDir("/path/to/your/project") 让后续所有命令在该 PHP 项目根目录下执行(等价于 composer --working-dir),是操作多项目时的关键开关。
  • 🌍 注入环境变量c.SetEnv([]string{...}) 设置 COMPOSER_MEMORY_LIMIT=2G(放宽内存限制)和 COMPOSER_NO_INTERACTION=1(禁用交互式提问),保证命令在 CI / 守护进程中静默、稳定运行。
  • 🔄 Composer 自更新c.SelfUpdate() 封装了 composer self-update,把本地 Composer 升级到最新稳定版。它可能因权限或网络失败,故用 log.Printf 记录而非 log.Fatalf 中断。
  • 🛡️ 错误处理策略:查询型命令(--version)失败用 Fatalf 快速暴露;副作用型命令(diagnoseself-update)失败用 log.Printf 容错继续,体现「初始化致命、运行期可恢复」的分层思路。

▶️ 运行方式

本示例以 Example 函数形式编写,需在示例目录下显式运行对应文件:

bash
cd /home/cc11001100/github/scagogogo/composer-skills/examples/cli_basic_usage
go run 02_run_commands.go

⚠️ CLI 示例需要本地安装 PHP 和 Composer;若未安装,SDK 会尝试自动安装。SelfUpdate 会真实升级本地 Composer,建议在测试环境中运行。运行前请把 SetWorkingDir 的路径替换为你本机真实存在的 PHP 项目目录。

📚 涉及的 SDK 方法

方法名所属包作用文档链接
Newpkg/composer根据选项构造 *Composer 客户端实例/sdk/composer/methods/quick-setup
Runpkg/composer透传参数执行 Composer 命令,返回输出字符串/sdk/composer/methods/run
RunWithContextpkg/composerRun,但接受 context.Context 支持超时/取消/sdk/composer/methods/run-with-context
SetWorkingDirpkg/composer设置后续命令的工作目录/sdk/composer/methods/set-working-dir
SetEnvpkg/composer设置子进程环境变量/sdk/composer/environment
SelfUpdatepkg/composer执行 composer self-update 升级 Composer/sdk/composer/methods/self-update

📝 说明:SetEnv 通过批量注入环境变量影响子进程,与单变量级别的 SetEnvVariable 同属环境配置体系,故链接指向 environment 总览页便于对照。

🚀 进阶

  • ⏱️ 统一超时:把 RunWithContext 的超时抽成常量,并对不同命令分级(查询 5s、安装 300s),结合 run-with-timeout 风格的便捷封装避免每次手写 context.WithTimeout
  • 📋 结构化输出Run 返回原始字符串,需要版本号、依赖树等结构化数据时改用 GetVersionInfoShowDependencyTree 等类型化方法,省去正则解析。
  • 🧪 可测试性:将 *Composer 通过接口注入业务代码,便于在单测里用 stub 替换 Run,避免真实拉起子进程。
  • 🔁 失败重试:对 SelfUpdatediagnose 等易因网络波动的命令包一层指数退避重试,并在重试耗尽后上报监控。
  • 🗂️ 多项目编排:用 SetWorkingDir 在多个项目间切换时,配合 c.SetEnv 注入项目级 COMPOSER 配置文件路径(COMPOSER=composer.prod.json),实现一套客户端驱动多套部署清单。
  • 🔐 权限与隔离:在生产环境运行 SelfUpdate 前,先 GetVersionInfo 比对当前版本与目标版本,必要时锁定到指定版本而非盲目升级到 latest,避免破坏性变更。

基于 MIT 许可证发布