Composer不支持npm风格的@scope/package语法,因解析器在tokenize阶段即拒绝含@的包名;合法包名须为vendor/name格式,如myorg/foo,并需配置repositories才能加载私有包。

Composer 本身不支持 npm 风格的 @scope/package 语法,强行模仿只会导致 composer require 失败或 autoload 错乱——因为 Packagist 和 Composer 的解析器根本不识别 @ 前缀作为命名空间分隔符。
Composer 里写 @vendor/name 会直接报错
运行 composer require @myorg/mylib 会立刻抛出 [InvalidArgumentException] Package @myorg/mylib not found.。这不是网络或镜像问题,是 Composer 解析器在 tokenize 阶段就拒绝了含 @ 的包名。Packagist 的包名规则强制为 vendor/name(字母、数字、下划线、短横线),@ 不在合法字符集内。
- 所有带
@的字符串都会被 Composer 当作非法标识符拦截,连请求 API 都不会发出去 - 试图在
composer.json的require中硬写"@myorg/mylib": "^1.0",composer validate就会失败 - 别指望改
repositories类型(如package或path)能绕过这个校验——包名合法性检查发生在解析阶段,早于仓库查找
想实现“作用域隔离”,得用 vendor 名模拟 scope
npm 的 @myorg/foo 在 Composer 生态中对应的是 myorg/foo(注意:不是 myorg-foo)。这是 Packagist 官方推荐的命名惯例,也是 Laravel、Symfony 等主流项目实际采用的方式。
-
myorg/foo是合法包名,可正常发布到 Packagist 或私有仓库(如 Satis、Private Packagist) - 如果你控制私有仓库,可在仓库前端加路径前缀(如
https://repo.myorg.com/packages/myorg/),但 Composer 侧仍用myorg/foo引用 - 避免用
myorg-foo:它语义上是“一个叫 myorg-foo 的独立包”,而非“myorg 作用域下的 foo”;后续扩展(如myorg/bar)会失去命名一致性 - 若已有 npm 包名
@myorg/foo,PHP 包应统一迁移到myorg/foo,并在文档里注明映射关系
私有 scope 包必须配 repositories 才能 require
即使你用了 myorg/foo 这种合法名,只要没发布到 Packagist,Composer 就找不到它——默认只查 packagist.org。必须显式声明仓库位置。
- 最常用的是
type: "composer",指向私有 Packagist 兼容服务:"repositories": [ { "type": "composer", "url": "https://repo.myorg.com" } ] - 如果是单个本地包,用
type: "package",但必须手写完整composer.json元数据,包括name、version、dist源等,稍有遗漏就会Class not found - 绝对不要把私有包放
vendor/下手动拷贝——composer install --no-dev会清空整个vendor,你的手动操作瞬间失效 - 配置完
repositories后,运行composer clear-cache再composer require myorg/foo,否则可能命中旧缓存返回 404
autoload 映射要匹配实际命名空间,不是 scope 名
包名 myorg/foo 不代表类必须放在 MyOrgFoo 命名空间下。Composer 只管按 autoload 规则加载,和 vendor 名无关。常见错误是以为 “scope 名 = 根命名空间”。
- 如果
myorg/foo的composer.json里写的是"autoload": {"psr-4": {"App\": "src/"}},那它的类就在App*下,跟myorg无关 - 更合理的做法是让命名空间与 vendor 名对齐:
"autoload": {"psr-4": {"MyOrg\Foo\": "src/"}},这样use MyOrgFooSomething;语义清晰 - 你自己项目 require 了
myorg/foo后,如果它的 autoload 没生效,先检查vendor/myorg/foo/composer.json是否真写了 autoload 字段,再运行composer dump-autoload - 别在自己项目的
autoload里去映射myorg/foo的路径——那是包自己的事;你只需确保它被正确安装且其 autoload 已被 Composer 注册
真正麻烦的从来不是名字怎么写,而是当团队里有人坚持用 npm 思维写 @myorg/foo 并提交到 git,CI 流水线会卡在 composer install 第一步。这时候删错字符比解释原理更快。











