composer自定义命令分scripts脚本和composer-plugin插件两种机制:scripts需在composer.json根级配置、手动加载autoloader、传参用--分隔;插件必须声明type:"composer-plugin"、实现commandproviderinterface、继承basecommand,且安装后才出现在composer list中。

Composer 自定义命令不是“写个 PHP 类扔进去就生效”的事——它分两种完全不同的机制:一种是 scripts 字段驱动的轻量级自动化任务,另一种是 composer-plugin 类型包实现的、能出现在 composer list 里的真命令。选错路径,90% 的问题都出在根本没走对流程。
scripts 字段怎么配才真正可运行
scripts 是最常用也最容易翻车的方式。它不注册新命令,只是把键名映射成 shell 或 PHP 调用,所有行为都受限于 Composer 的执行模型。
- 必须放在
composer.json根层级,和require同级;嵌套在extra或config里直接无效 - 键名就是命令名:
"test:unit"→ 运行时得写composer run-script "test:unit"(带双引号,冒号在 shell 里有特殊含义) - 值支持字符串、字符串数组或
"MyClass::method"形式;但后者要求类已声明在autoload中,且必须是public static - PHP 回调不会自动加载
vendor/autoload.php,第一行得手动加require __DIR__ . '/../vendor/autoload.php'; - 传参必须用
--显式分隔:composer test -- --filter=TestFoo,否则参数被 Composer 吞掉
为什么你的命令没出现在 composer list 里
只有通过 composer-plugin 类型包 + CommandProviderInterface 实现的,才会被 composer list 扫描到。脚本命令永远不会出现。
围绕关键发现、作用机制、临床相关性及研究局限性展开讨论。适用于撰写或优化任何生物医学论文的“讨论(Discussion)”部分——包括结果解读、与既往文献关联、阐释意外发现、界定研究局限性,以及撰写结论。当用户输入以下任一指令时也会自动触发该功能: - “write my discussion” - “help me discuss my findings” - “how do I compare to prior studies” - “write the limitations par
- 插件包的
composer.json必须声明"type": "composer-plugin"和兼容的"composer-plugin-api"版本(如"^2.0") - 主类必须实现
ComposerPluginCommandProviderInterface,且getCommands()返回ComposerCommandBaseCommand实例数组 - 不能继承
SymfonyComponentConsoleCommandCommand—— 必须继承ComposerCommandBaseCommand,否则拿不到$this->getComposer() - 插件必须已安装(
composer require my/plugin或全局composer global require),本地开发路径需通过repositories指向 - 构造函数或
activate()抛异常会导致插件被静默跳过,不报错也不注册命令
PHP 回调里 Class not found 怎么快速定位
这不是 autoload 配置错了这么简单,而是 Composer 执行 scripts 时根本不加载 autoloader,连 vendor/autoload.php 都不碰。
- 检查
composer.json的autoload是否包含该类路径,例如:"psr-4": { "AppScripts\": "scripts/" } - 改完
autoload后必须运行composer dump-autoload,否则新路径不可见 - 脚本文件里第一行加防护:
if (!class_exists('ComposerAutoloadClassLoader')) { die('autoload not loaded'); } - 别依赖
$_SERVER['argv']取参——Composer 不透传原始参数;改用getenv('COMPOSER_ARGS')或提前在 shell 层拼好命令 - 方法必须是
public static,且不能 new 未声明在autoload中的第三方类(比如直接new IlluminateSupportStr)
插件命令里怎么安全读取项目信息
插件运行时工作目录不等于项目根目录,硬编码路径或 file_get_contents('composer.json') 极易失败。
- 当前项目元数据统一从
$this->getApplication()->getComposer()->getPackage()拿,不是读文件 - 配置项(如
vendor-dir)必须用$this->getApplication()->getComposer()->getConfig()->get('vendor-dir') - 想访问 extra 字段?用
$package->getExtra(),比自己解析 JSON 安全且已 normalize - 不要在
execute()里调exec('composer install')—— 可能引发嵌套加载、锁文件冲突 - 全局插件和本地插件作用域不同:全局插件每次启动都会加载;本地插件只在 vendor 存在且 autoloader 可用时才生效
真正麻烦的从来不是写代码,而是搞清 Composer 在哪个阶段加载了什么、谁控制入口、上下文从哪来。插件命令要绕过 Composer 的生命周期管理,脚本命令要扛住不自动加载 autoloader 的现实——这两条路,走岔一步,命令就“看不见”或“跑不动”。










