用 composer create-project 搭建扩展包模板比手动创建快5倍以上且规避90%高频错误,因其预置合法 name、autoload 路径和 PHP 版本约束,而 composer init 缺乏关键校验易致 Packagist 发布失败。

直接用 composer create-project 搭建扩展包模板,比手动建目录、写 composer.json、配 autoload 快 5 倍以上,且能规避 90% 的命名空间路径错位、vendor 名非法、PHP 版本漏约束等高频错误。
为什么不用 composer init 起步?
composer init 是交互式向导,适合单次快速初始化简单项目,但对扩展包来说,它不校验关键约束:比如 name 字段是否含 vendor、autoload 路径是否以斜杠结尾、php 版本是否显式声明。这些漏掉一项,后续发布到 Packagist 就会失败,或本地 require 报 Package name must be lowercase...。
- 它默认把
name设成myapp,而正确格式必须是vendor/name(如acme/utils) - 它允许你输
src作为 PSR-4 路径,但实际要写"src/"(末尾斜杠不可少) - 它不提示加
"php": "^8.1"到require,导致 CI 构建时拉错依赖版本
用 create-project 拉标准模板的实操要点
先找一个已验证的轻量模板,比如官方推荐的 php-pkg/skeleton 或社区维护的 orchestra/package-skeleton。执行命令时注意三个关键参数:
- 必须指定目标目录,避免覆盖当前项目:
composer create-project php-pkg/skeleton my-utils - 加
--no-interaction防止脚本卡在交互环节(尤其 CI 中) - 首次运行后立刻进目录执行
composer dump-autoload -o,确保新结构下的类可被自动加载
模板生成的 composer.json 里通常已预置好 "type": "library"、"autoload": {"psr-4": {"AcmeUtils": "src/"}} 和 "require": {"php": "^8.1"} —— 这些不是“建议”,而是 Packagist 接收和 Composer 正常解析的硬性门槛。
name 和 autoload 错位是最常踩的坑
很多人改完 name 为 acme/utils,却忘了同步改命名空间前缀和 autoload 映射。结果是 composer dump-autoload 成功,但 new AcmeUtilsCalculator() 仍报 Class not found。
-
name中的acme必须与命名空间前缀完全一致(大小写敏感),不能是ACME或acme_ -
"Acme\Utils\": "src/"的双反斜杠是 PHP 字符串转义必需,写成"AcmeUtils"会解析失败 -
src/是相对于composer.json的路径,若模板把源码放在lib/,就必须同步改成"Acme\Utils\": "lib/"
发布前必须验证的三件事
模板生成只是起点,发布到 Packagist 前得确认这三项真实生效:
- 运行
composer validate:它会检查name格式、autoload路径是否存在、php约束是否合法 - 执行
composer show acme/utils(本地未安装时会报错,说明name还没被识别;成功则显示基本信息) - 手动
require 'vendor/autoload.php'并实例化一个类,验证 autoload 是否真能定位到文件 —— 很多模板的src/下是空的,或示例类命名空间写错了
真正麻烦的从来不是建结构,而是 vendor 名、命名空间、PSR-4 路径、composer.lock 四者之间那条隐性绑定线——断一处,整个自动加载就静默失效,还查不出错在哪。


















