Composer Installer 这个插件,名字听起来像“用于安装 Composer 的工具”,但千万别被名称误导。它的真正作用在于:让第三方包能够按照你项目的框架规范,准确放置到正确的位置。换句话说,当你安装一个 WordPress 插件时,它应该被放到 wp-content/plugins/ 目录,而不是被遗弃在 vendor/ 中。这一切,都由它来负责调度。

然而,很多开发者在兴奋地执行 composer require composer/installers 之后,发现插件并没有按预期工作。问题究竟出在哪里?今天我们就一次性梳理几个最容易踩的坑,帮你彻底搞懂。
你安装了插件,但包没有“搬家”?请先检查包的 type 字段是否正确
这是最常见的错误之一。很多人以为只要本地安装了 composer/installers,所有依赖就会自动被“搬运”到对应的目录。实际上,composer/installers 只是一个“搬运工”,它并不负责判断包应该去哪里,只负责执行搬运指令。而指令的来源,是你要安装的那个包自身声明的 type 字段。
- 一个 WordPress 插件,必须在它的
composer.json中明确指定"type": "wordpress-plugin",搬运工才会将它移动到wp-content/plugins/目录。 - 如果它声明的是
"type": "library",或者根本没有type字段,那么无论你怎么折腾,它都会乖乖待在vendor/中。 - 验证方法很简单:安装完成后,先查看
vendor/下是否存在这个包。如果没有,说明它已经被搬走了,再去目标目录(比如wp-content/plugins/)中查找即可。
因此,不要指望通过修改自己项目的配置来“强制”一个未声明 type 的通用包进入特定目录——它根本不会触发搬运逻辑。
自定义 installer-paths 时,路径变量的写法最容易出错
这个坑也很常见。很多人喜欢在 installer-paths 中玩花样,比如想加入版本号之类的信息。但这里有一个硬性限制:它只支持 {$name} 和 {$vendor} 这两个变量插值,{$version} 是不被识别的。
- 正确的写法:
"wp-content/plugins/{$name}/": ["type:wordpress-plugin"] - 错误的写法:
"wp-content/plugins/{$name}-v{$version}/": [...]—— 这种写法中{$version}不会被解析,最终要么生成空目录,要么直接报错。 - 路径结尾的斜杠
/不能省略,否则在 Windows 下可能因为路径分隔符问题导致创建失败。 - 多个规则写在数组里,顺序不重要,但匹配优先级由
composer/installers内部实现决定,不建议依赖顺序来控制逻辑。
升级到 Composer 2.5+ 后配置失效?请检查 key 名的拼写
Composer 2.4 起,配置项依然叫 installer-paths(拼写未变),但很多人会误写成 installers-paths 或 install-path。这类拼写错误不会报错,只会被静默忽略——你配了跟没配一样。
- 必须严格使用:
"installer-paths"(注意是installer,不是installers)。 - 完整结构示例:
{ "extra": { "installer-paths": { "wp-content/plugins/{$name}/": ["type:wordpress-plugin"], "app/Modules/{$name}/": ["type:lara vel-module"] } }} - 验证是否加载成功:运行
composer config extra.installer-paths,输出应为对应的 JSON 对象;若为空,说明 key 写错了,或者没有放在顶层extra下。
为什么 vendor/ 里还有包残留?composer dump-autoload 不管用
另一个常见误区:认为 composer dump-autoload 能够重新排列包的位置。实际上,composer/installers 是“安装时”行为,与自动加载完全无关。它只影响 composer install 或 composer update 时的文件落点。
- 残留在
vendor/中的包,通常是因为之前没有配置installer-paths,包已经下载到了那里。新配置完成后,旧包不会自动被搬走。 - 解决方法:手动删除
vendor/xxx/yyy目录,然后重新执行composer install或composer update xxx/yyy。 - 另外,如果一个包既出现在
installer-paths规则里,又出现在require列表中,它仍然会被复制过去——installer-paths并不会阻止vendor/下存在副本,只是多建一份软链接或硬拷贝(取决于具体实现)。
总结一下,composer/installers 的核心逻辑非常简单:你配置正确了,包也声明了正确的 type,它才会老老实实工作。否则,一切努力都是白费。记住这一点,以后就不会再为“为什么没生效”而抓狂了。
