对标 npx 的 CPX PHP 的 Composer 包执行器

对标 npx 的 CPX PHP 的 Composer 包执行器

cpx CLI 可以从任意 Composer 包中运行命令,而无需将该包安装到项目中------cpx 之于 Composer,正如 npx 之于 npm。

如果曾经使用 composer global require 安装过某个工具,随后又遇到它与其他全局安装工具之间的依赖冲突,cpx 以隔离依赖的方式即可解决这一问题。

cpx 会将每个包安装到各自独立的目录中,既与项目的依赖隔离,也与全局 Composer 环境隔离,然后从该目录运行命令。同一版本的重复运行会复用已有的安装,cpx 还会在运行过程中检查更新。

运行尚未安装的包

传入包名,后跟命令及其参数。此处的包名即通常写入 composer.json 的包名,并支持版本约束:

bash 复制代码
cpx friendsofphp/php-cs-fixer php-cs-fixer fix ./src
cpx friendsofphp/php-cs-fixer:^3.0 php-cs-fixer fix ./src

当包只有一个可执行文件,或者其可执行文件与包名一致时,可以省略命令:

bash 复制代码
cpx friendsofphp/php-cs-fixer fix ./src

如果包包含多个可执行文件而用户未指定具体哪一个,2.0 会提示用户进行选择。

也可以让 cpx 指向一个目录而非包名,这在本地开发包时非常有用:

bash 复制代码
cpx ../my-package --version

该目录需要包含有效的 composer.json,且其依赖已安装就位(vendor/autoload.php)。cpx 会直接从该检出目录运行声明的可执行文件,不会复制、缓存或以其他方式管理它。

默认优先使用本地可执行文件

这是对使用过 1.x 的用户最可能产生影响的行为变更。现在 cpx 会先在项目中查找可执行文件,然后才安装隔离副本。它会从当前目录逐级向上查找最近的 Composer 项目,并运行该项目所配置 bin-dir 中的匹配可执行文件:

bash 复制代码
cpx pint                 # runs vendor/bin/pint when the project has it
cpx phpunit --filter=Foo # runs vendor/bin/phpunit when present
cpx laravel/pint:^2.0    # uses the local pint only if it satisfies ^2.0

因此,在项目内部,cpx pint 运行的是项目所固定的版本,而非最新版本。当不存在匹配的本地可执行文件时,cpx 会回退为安装并运行隔离副本。如需强制使用隔离副本,可在包名之前传入 --skip-local。

别名改由用户自行定义

1.x 版本内置了一份针对流行包的固定快捷方式列表,因此 cpx phpstan 和 cpx laravel 开箱即用。这份列表在 2.0 中已被移除,改为由用户自行定义:

bash 复制代码
cpx alias phpstan/phpstan phpstan
cpx alias laravel/pint

省略别名时默认采用包的短名称,因此上面的第二行创建了别名 pint。别名存储在 ~/.cpx/ 目录下,cpx aliases 可列出全部别名,cpx unalias <name> 可删除某个别名。也可以为包含多个可执行文件的包中的某个特定可执行文件创建别名。

还有两个值得了解的管理命令:cpx installed 列出通过 cpx 运行过的包,cpx clean 移除最近未使用过的包(--all 删除全部)。注意,cpx list 现在显示的是可用的 cpx 命令------这是标准的控制台行为------而非已安装的包。

运行 PHP 文件、Gist 与 REPL

cpx exec 和 cpx tinker 用于处理零散脚本与快速的一次性任务:

bash 复制代码
cpx exec script.php
cpx exec -r 'echo PHP_VERSION;'
cpx exec https://gist.github.com/user/id
cpx tinker

Gist 支持会下载文件并在当前目录下运行。如果 gist 包含多个 PHP 文件,cpx 会询问运行哪一个,也可以附加 gist 页面上的文件锚点以跳过提示。附加 SHA 可固定到特定修订版本,而设置 GITHUB_TOKEN 可以绕过 GitHub 的速率限制。

这两个命令都会在用户代码运行之前执行一些准备工作。这两个命令会检测当前目录或父目录中的 Composer 自动加载器(autoloader)。对于未通过 import 引入就使用的类,cpx 会在能够找到匹配项时为其建立别名。在 Laravel 项目中,应用会被完全启动,config、facades、.env 与 app均可用;在Symfony项目中,内核会启动并暴露app 均可用;在 Symfony 项目中,内核会启动并暴露 app均可用;在Symfony项目中,内核会启动并暴露kernel 与 $container。传入 --no-boot 可跳过上述过程。用户代码运行在独立的 PHP 进程中,因此不会与 cpx 自带的依赖冲突,exit() 退出码也会原样传递。

在这些脚本内部,cpx_require() 可按需引入某个包:

php 复制代码
cpx_require('nesbot/carbon');
 
echo Carbon\Carbon::now();

在安装了 laravel/tinker 的 Laravel 项目中,cpx tinker 会将控制权移交给项目自身的 php artisan tinker,并转发 --execute 之类的参数。在其他环境中,它会在项目启动完成后打开一个 PsySH shell。

感知代理环境的输出

cpx 能够检测到自身未连接交互式终端的情况。这包括 stdin 被重定向、传入了 --no-interaction 或 -n,以及在 AI 代理中运行------这种情况通过 laravel/agent-detector 识别。

在该模式下,子进程不会获得 TTY,交互提示回退为默认值,管理命令(installed、aliases、alias、unalias、clean 和 update)返回单行 JSON:

json 复制代码
{
    "success": true,
    "errors": [],
    "summary": {
        "packages": [
            { "name": "laravel/pint", "last_run": "2024-01-02 03:04:05" }
        ]
    }
}

包运行时仅以流式方式输出底层工具自身的输出,cpx 自身的进度渲染会被抑制。cpx 层面的失败,例如无法识别的命令或无法安装的包,同样以 JSON 形式报告。传入 --json 可在交互式终端获得相同的输出。在非交互方式下覆盖已有别名需要 --force。

安装与升级

cpx 2.0 需要 PHP 8.3 或更高版本。使用 Composer 进行全局安装,并确保 Composer 的全局 bin 目录已加入 PATH:

bash 复制代码
composer global require cpx/cpx

了解更多

CPX 最初由 Liam Hammett 创建。CPX 2.0 现已成为由 Laravel 官方维护的 laravel/cpx 包,拥有来自 Laravel 的众多贡献者。如需观看现场演示,Taylor Otwell 已在波士顿举办的 Laracon US 2026 首日主题演讲中介绍并演示了 CPX 2.0。

完整命令参考可查阅 laravel/cpx GitHub 仓库。如果正在使用 1.x,可参阅 1.x 至 2.x 升级指南以开始使用 2.x,并可访问 cpx.dev 上精美的落地页。

原文链接 对标 npx 的 CPX PHP 的 Composer 包执行器

相关推荐
AINative软件工程1 小时前
LLM 多租户 Quota 工程实践:Token 配额、用量预警与自动熔断的生产设计
后端·llm·ai编程
Ivanqhz1 小时前
php7 闭包实现
开发语言·后端·rust·php
有梦不弃9 小时前
模块化单体架构设计方案:DDD + 六边形架构落地实践
后端·架构
XR1234567889 小时前
工厂车间无线网络方案对比:AGV漫游哪家强?
开发语言·php
現実君11 小时前
【硬件进阶】AD22上位替换JLEDA教程
开发语言·php
江南十四行14 小时前
Spring框架核心(上)——IoC控制反转与DI依赖注入详解
java·后端·spring
IT_陈寒14 小时前
Redis缓存击穿把我坑惨了,原来这样设过期时间才靠谱
前端·人工智能·后端
妙码生花15 小时前
从 PHP 到 AI + Golang,程序员自救转型手记(五十二):管理员权限检查中间件,AI 随意放行预闯大祸
前端·后端·go
创安电气研究所15 小时前
用 Node.js 将变频器运行数据接入 MQTT
后端