Composer 没有内置 license 或 licenses 命令,官方从未实现;唯一原生可用的是 composer show,但需已执行 install 且 2.5+ 版本移除了 --licenses;准确合规清单应解析 composer.lock 或使用 zicht/composer-license-plugin 插件。

composer license 命令根本不存在,运行即报错
直接告诉你结论:composer license 和 composer licenses 都不是 Composer 内置命令。你敲下去只会看到:Command "license" is not defined.——这不是你环境没配好,是它压根就没被实现过。官方从 1.x 到 2.5+ 全系列都不支持这两个命令,所有教程里出现的「运行 composer licenses 查看协议」都是基于插件或误传。
真正能用的原生命令只有 composer show
composer show 是唯一可靠、无需额外安装的入口,但它有严格前提和局限:
- 必须已执行过
composer install,否则vendor/下没包,show直接报Package not found -
composer show --licenses在 Composer 2.5+ 中已被移除;旧版虽有,但输出不结构化、不递归、不处理数组型 license(如["MIT", "Apache-2.0"]) - 想批量导出?得加
--format=json+jq:composer show --no-dev --format=json | jq -r '.[] | "\(.name),\(.version),\(.license // "unknown")"' - 注意:
--no-dev排除开发依赖;若需包含,换成--dev,但会混入 PHPUnit、PHPStan 等工具类许可,干扰生产合规判断
要生成可审计的许可证清单,必须用插件或解析 composer.lock
composer.lock 才是事实来源——它记录了实际安装的每个包及其精确 license 字段(含数组、null、空字符串)。比 composer show 更全、更准,也不依赖 vendor 是否完整:
- 用
jq快速统计分布(Linux/macOS):jq -r '.packages[].license | if type == "array" then .[] else . end | select(. != null and . != "")' composer.lock | sort | uniq -c | sort -nr - 用 PHP 脚本处理缺失字段更稳妥(无额外依赖):
json_decode(file_get_contents('composer.lock'), true)后遍历$lock['packages'],对$pkg['license'] ?? ['unknown']做(array)强转再展开 - 插件推荐
zicht/composer-license-plugin:装完就有composer licenses --format=json,还能启发式识别 LICENSE 文件内容(比如 license 字段为空但根目录有 MIT License 文本)
许可证字段只是元数据,不能替代法律合规审查
你看到 "license": "MIT",不代表这个包真的能用在你的闭源产品里——因为:
- 有些包声明 MIT,但实际代码里混入了 GPL 片段(需用
FOSSA或ScanCode扫描源码) -
proprietary或UNLICENSED意味着禁止分发,但composer show可能只显示unknown,你得手动打开 GitHub 仓库翻 LICENSE 文件 - 嵌套依赖的传染性条款不会被任何命令自动识别:主依赖是 MIT,它依赖的子包是 AGPLv3,整条链就受约束——这只能靠人工查
composer show --tree+ 对照 SPDX 许可兼容矩阵
最常被忽略的一点:Packagist 上同步的 composer.json license 字段可能滞后于 Git 仓库最新提交,composer.lock 里的值才是你此刻实际用到的,但即便如此,它仍可能漏掉未声明的隐含许可。










