Composer 的 type 字段是生态“身份证”,非安装开关;官方标准值有 library、project、metapackage、composer-plugin 及框架专用型,自定义 type 需配套 installer 否则无效。

Composer 的 type 字段不是安装开关,而是生态“身份证”——它不改变 composer install 怎么跑,但决定别人怎么用你、工具链怎么认你、Packagist 怎么分组你。
哪些值是官方认的?别瞎写自定义 type
Composer 官方明确定义了几个标准 type 值,只有这些才能被 Packagist 接收、被 composer/installers 等主流插件识别。写错或乱造(比如 "type": "my-framework")等于没写——Composer 会默默当 library 处理。
-
library:默认值,不写也自动算它;适合提供类、函数、接口的可复用包 -
project:表示“这是个完整应用”,比如 Laravel 官方 starter;会被composer create-project选中,不该 被其他项目require -
metapackage:纯依赖清单,不能含任何 PHP 文件,否则 Packagist 拒绝收录 -
composer-plugin:必须实现Composer\Plugin\PluginInterface,否则 Composer 启动时直接报错 - 框架专用型如
wordpress-plugin、cakephp-plugin:需搭配对应 installer 才生效,单写 type 没用
type: library 和 type: project 到底差在哪?
表面看只是个字符串,实际影响的是协作预期和工具行为。很多人以为改了 type 就能控制安装路径——其实不能,真正起作用的是 composer/installers 是否注册并匹配了该 type。
工作流任务拆解与模型编排技能。使用场景:(1) 收到复杂工作任务需要拆解为可执行步骤,(2) 需要为不同步骤选择最合适的模型,(3) 需要跟踪工作流进度和模型使用情况,(4) 长时间任务卡住需要问题诊断和解决方案。
- 设为
library:你的包会被require进别人项目,装进vendor/author/name,自动加载按autoload配置走 - 设为
project:别人运行composer create-project vendor/name时,Composer 会把它当模板克隆;但如果你在自己项目里写了"type": "project"又同时被其他项目require,就可能引发循环依赖警告 - 常见错误:
laravel/laravel是project,但你自己的业务项目如果也标project却还放一堆require-dev工具包,容易让 CI 误判部署目标
metapackage 为什么一放 src 就失败?
metapackage 的设计哲学是“零代码,纯声明”。Packagist 在审核时会扫描所有文件,只要发现 src/、tests/、bin/ 或任何 PHP 文件,就会拒绝发布,并提示类似 Package of type metapackage cannot contain autoloading configuration or files 的错误。
- 必须删掉
autoload、autoload-dev、bin字段 -
require列表可以有 dev 版本(如"monolog/monolog": "dev-main"),但整包不能含任何可执行逻辑 - 典型用途:统一安装 PHP 开发工具集(
phpunit+phpcs+infection),或锁定某套兼容版本组合
type 不写会怎样?写了又没配对 installer 呢?
不写 type,Composer 默认当 library;写了却没配套 installer(比如写了 wordpress-plugin 但没装 wpackagist 或对应插件),那它还是按 library 装进 vendor,不会进 wp-content/plugins。
- 自定义 type(如
"type": "myapp-module")必须自己写 installer 并在composer.json中声明"extra": {"installer-name": "myapp-module"},否则完全无效 - 想让包被正确归类到 Packagist 的标签页(比如显示为 “WordPress Plugin”),只写 type 不够,还得确保 Packagist 支持该类型(查 Packagist types 文档)
- 最常被忽略的一点:
type影响composer validate的校验规则——比如metapackage下出现autoload会直接 fail
type 字段真正的复杂点不在语法,而在它把“你是谁”这个语义问题,塞进了工具链的每个环节:从 Packagist 的分类页,到 CI 脚本判断是否打包为 Docker 镜像,再到团队新人看到 type: project 就知道不该去 require 它——稍不注意,就变成文档和行为割裂的隐性坑。

















