description字段必须为非空字符串且位于composer.json根层级,否则Packagist拒收;需动词开头、含技术锚点、无形容词,长度≤120字符;修改后需手动更新或触发webhook同步。

description 字段必须是字符串,写在 composer.json 根层级,空值或格式错误会导致 Packagist 拒收、composer require 找不到包。
description 字段必须写对位置和类型
它不是配置项,也不是可选注释——Packagist v2 起强制校验非空字符串。写错位置(比如塞进 extra 或 autoload)、写成数组({"en": "..."})、写成 null 或空格,都会被忽略,且不报错。
- ✅ 正确位置:
composer.json最外层大括号内,与name、type并列 - ✅ 正确写法:
"description": "Sends HTTP requests with retry and timeout" - ❌ 错误写法:
"description": null、"description": ["sends http"]、"extra": {"description": "..."} - ⚠️ 末尾逗号:如果
description后面还有字段(如keywords),它行尾必须有英文逗号;如果是最后一个字段,则不能有逗号
写什么才不算废话——动词开头 + 技术锚点 + 无框架依赖说明
Packagist 搜索页只显示前约 120 字,截断后还得能独立传达价值。用户搜的是“做什么”,不是“多厉害”。
- 以动词起手:
Generates、Validates、Provides、Converts,别用A、An、This package - 带一个真实技术锚点:
PSR-14、Laravel 11、PHP 8.3+、OAuth2,但版本号建议移入require.php,这里优先留协议/标准/生态关键词 - 说明约束更关键:比如
no dependencies、zero-config(指行为上无需配置,不是营销话术)、works offline - 避免形容词:
lightweight、modern、awesome全部删掉——Packagist 不索引,人也不信
改了 description 为什么没更新?同步和缓存是两回事
composer.json 本地改完 ≠ Packagist 页面立刻刷新。它不监听 Git push,也不自动拉取,得靠触发机制。
- 手动更新:登录 Packagist 对应包页,点
Update按钮(页面右上角) - 自动更新:确保 GitHub/GitLab 仓库已正确绑定 webhook,且推送包含
composer.json变更的 commit - 验证是否生效:运行
composer show vendor/name(本地已安装)或访问 Packagist 页面看首屏文案 - 常见卡点:改了但忘记 push;push 了但 webhook 失败(检查仓库 Settings → Webhooks);
composer validate通过不代表 Packagist 接受——它有额外校验逻辑
description 和 keywords、README 是分工关系,不是重复关系
三者各干各的活,混着写只会稀释信息密度。
-
description:一句话功能定位,给机器扫描+人快速扫读,≤120 字,纯文本,无链接无换行 -
keywords:数组,填 3–5 个真实搜索词,如["psr-14", "event-dispatcher", "symfony"],别填php、library -
README.md:唯一被 Packagist 渲染的文档文件,放安装命令、示例代码、配置说明——description里绝不能出现这些 - ⚠️ 注意:
composer.json里的readme字段(如"readme": "README.md")完全无效,Packagist 只认根目录真实存在的README.md文件
最容易被忽略的一点:description 空着不会让 composer install 报错,但会让整个包在 Packagist 上“隐形”。你本地能 require,别人搜不到、IDE 补全不提示、CI 构建时也容易因元数据缺失失败——它不是技术障碍,是发现障碍。











