composer的runtime-api是插件兼容性开关,仅用于插件加载时校验版本匹配;真正的运行时检查应使用installedversions类,它提供包存在性、版本、路径等动态查询能力。

Runtime组件不是运行时API,而是插件兼容性开关
很多人看到 runtime-api 就以为是 Composer 提供的“运行时调用接口”,其实它压根不参与依赖安装、自动加载或命令执行。它只在插件加载阶段起作用:Composer 读取插件的 composer.json 中声明的 "composer-runtime-api": "^2.5",再比对自身 ComposerRuntimeApi::VERSION 字符串,不匹配就跳过该插件,避免因接口变更导致 fatal error。
这意味着你无法用它检测项目是否“能跑”,也不能靠它判断 PHP 版本或扩展是否满足——那些属于 platform-check 或 check-platform-reqs 的职责。
- 插件作者误把
runtime-api当成功能开关(比如据此决定是否启用新参数),结果在旧版 Composer 上行为异常 - 开发者试图用
composer show --all composer/composer查 runtime-api 版本,但这个值不在包元数据里,查不到 - CI 环境中硬编码
COMPOSER_RUNTIME_API=2.5环境变量,完全无效——Composer 不读这个变量
真正可用的 Runtime 自检工具是 InstalledVersions 类
Composer 2.0+ 内置的 \Composer\InstalledVersions 才是你能在代码里直接调用的、可靠的运行时版本检查组件。它不依赖插件机制,只要 vendor/autoload.php 被引入就能用。
常见使用场景包括:
围绕关键发现、作用机制、临床相关性及研究局限性展开讨论。适用于撰写或优化任何生物医学论文的“讨论(Discussion)”部分——包括结果解读、与既往文献关联、阐释意外发现、界定研究局限性,以及撰写结论。当用户输入以下任一指令时也会自动触发该功能: - “write my discussion” - “help me discuss my findings” - “how do I compare to prior studies” - “write the limitations par
- 判断某个包是否已安装:
\Composer\InstalledVersions::isInstalled('monolog/monolog') - 验证版本是否满足约束:
\Composer\InstalledVersions::satisfies(new \Composer\Semver\VersionParser, 'laravel/framework', '^10.0') - 获取当前安装的精确版本:
\Composer\InstalledVersions::getVersion('symfony/http-foundation') - 区分 dev 和 prod 安装:
\Composer\InstalledVersions::isInstalled('phpunit/phpunit', false)(false表示排除require-dev)
注意:getVersion() 返回的是规范化版本(如 6.4.0.0),而 getPrettyVersion() 才返回带 v 前缀或 dev-main 这类可读字符串。
如何安全地在生产环境触发 Runtime 检查
别在每次 HTTP 请求入口处无差别调用 InstalledVersions 方法——它本身轻量,但频繁调用 satisfies() 会重复解析版本字符串,且没缓存。更稳妥的做法是:
- 只在关键路径上做一次检查,比如框架启动时校验核心依赖版本
- 用
getVersion()+version_compare()替代satisfies(),避免引入VersionParser实例开销 - 如果项目用了 opcache,确保
vendor/composer/InstalledVersions.php被正确缓存——这个文件由 Composer 自动生成,修改composer.lock后会重写,opcache 需要失效或重启 - 不要在 CLI 命令中依赖
isInstalled()判断是否存在,因为有些包可能只在require-dev里,而你用--no-dev安装了
容易被忽略的 Runtime 边界条件
InstalledVersions 只反映当前 vendor/ 目录下实际安装的包状态,它不感知未安装的依赖、不校验 autoload 是否生效、也不管 composer.json 里写的约束是否和 lock 文件一致。一个典型陷阱是:
- 你改了
composer.json的require,但忘了composer install,此时isInstalled()仍返回true(因为旧包还在 vendor 里),但新约束根本没生效 -
getInstallPath()返回的路径可能为空(比如包被 symlink 到全局 vendor),不能直接拼接文件路径 - 在多 Composer 项目共用同一
vendor/(如 monorepo 工具链)时,InstalledVersions会混合所有项目的安装状态,结果不可靠
真正要确认“当前环境能否运行”,得组合使用:composer install --dry-run(验证 lock 同步)、composer check-platform-reqs(验证 PHP/扩展)、再加上 php vendor/autoload.php 直接执行看是否 fatal error——InstalledVersions 只是其中一环,不是万能钥匙。










