provide字段仅在被require的包中有效,根项目声明无效;必须使用生态约定的虚拟包名如psr/cache-implementation,版本写"*"最安全;不解决自动加载,需单独配置autoload。

provide字段必须写在被require的包里,根项目声明无效
Composer 的 provide 字段不是给你的项目“打广告”用的,它只在你发布的包(比如一个自定义缓存驱动)中起作用。如果你在自己项目的 composer.json 里写 "provide": {"psr/cache-implementation": "*"},Composer 完全忽略——这个字段只对被其他项目 require 的包生效。
常见错误包括:
- 把
provide放在根项目中,以为能“告诉 Composer 我用了某实现”,实际毫无作用 - 发布包时漏掉
provide,导致依赖psr/cache-implementation的框架(如 Laravel、Symfony)无法识别你的包 - 拼错虚拟包名,例如写成
psr/cache(这是接口规范包),正确应为psr/cache-implementation
虚拟包名必须与生态约定一致,不能自创
Composer 不校验你是否真实现了接口,它只做字符串匹配。所以名字必须严格对齐已有约定,否则没人认。官方和主流框架认可的虚拟包名有:
-
psr/log-implementation:任何实现Psr\Log\LoggerInterface的包都该提供它 -
psr/http-client-implementation:Guzzle、Symfony HttpClient、HttpPlug 等都提供这个 -
ext-gd、ext-mbstring等:用于声明 PHP 扩展可用性,供其他包做条件依赖 -
laravel/framework:虽未真实发布,但某些包会require它来触发 Laravel 特定逻辑(注意:仅provide不够,需配合replace)
别写 myapp/cache-driver 这类自定义名——除非你已说服整个生态采纳它,否则只是废声明。
版本号写 "*" 最安全,写具体版本要担责
provide 的值是版本约束,不是实现版本。写 "*" 表示“我声称能替代任意版本的该虚拟包”,最常用也最宽松;写 "^3.0" 意味着你承诺兼容 PSR 规范 v3.x,但 Composer 不检查,运行时若行为不符(比如没实现新方法),崩的是使用者的程序,不是你的包。
典型正确写法:
"provide": {
"psr/cache-implementation": "*",
"ext-redis": "7.4.0"
}
注意:ext-redis 这种是声明扩展存在性,值填 PHP 扩展的版本号(来自 phpversion('redis')),不是你包的版本。
provide不解决自动加载,autoload仍需单独配
声明了 "psr/cache-implementation": "*",不代表类就能自动加载。Composer 只靠它解依赖,不碰 autoload。如果你的包没配 autoload 段,或者路径写错,composer install 成功后依然会 Class not found。
务必检查:
-
composer.json中是否有正确的autoload或autoload-dev配置 - 执行过
composer dump-autoload(尤其在开发阶段改了类路径后) - 类命名空间与文件路径是否符合 PSR-4 规则
最容易被忽略的一点:provide 生效的前提是这个包已被其他项目 require 并参与依赖解析;纯本地开发、没被依赖、也没发到 packagist 或私仓,那它就只是 JSON 里一行安静的文字。











