target-dir 已被 Composer 2.0 完全移除,应改用 psr-4 或 classmap 实现自动加载;包的物理安装路径由 name 字段决定,不可修改,静态资源分发可通过 scripts 配置 post-install-cmd 处理。

target-dir 已被弃用,别再用了
target-dir 是 Composer 1.x 早期版本中用于将包内某个子目录映射为安装路径的配置项,写在 composer.json 的 autoload 或 autoload-dev 下。但它在 Composer 2.0 中已被**完全移除**,任何使用它的包在 Composer 2+ 环境下会触发警告甚至失败——不是不生效,而是直接报错:target-dir is not supported anymore。
现在主流方案是改用 autoload 的 psr-4 或 classmap,配合正确的命名空间和目录结构来实现“逻辑安装位置”的效果。
想把类文件装到 vendor/xxx/yyy 目录下?你其实不需要 target-dir
Composer 安装包时的物理路径(如 vendor/myorg/mylib)由包名(name 字段)决定,无法通过 target-dir 或其他配置修改。所谓“指定安装目标目录”,本质是误解——Composer 不支持把一个包解压到非 vendor/{vendor}/{name} 的位置。
如果你的真实需求是:
- 让自己的类从
src/Utils被自动加载为MyOrg\Utils\*—— 用psr-4即可 - 想把第三方包的某部分代码“软链接”或“复制”到项目特定目录(如
public/js)——那是构建流程的事,该用scripts+post-install-cmd - 想让包发布时只暴露
dist/下的编译后文件 —— 应在.gitattributes中 excludesrc/,而非依赖target-dir
替代 target-dir 的正确 autoload 写法(PSR-4)
假设你的包结构是:
myorg/mylib/
├── composer.json
└── src/
└── Http/
└── Client.php
且你想让 MyOrg\MyLib\Http\Client 正确加载,composer.json 应这样写:
{
"autoload": {
"psr-4": {
"MyOrg\\MyLib\\": "src/"
}
}
}
关键点:
-
psr-4的 value 是相对于包根目录的路径,不是相对于vendor - 命名空间末尾必须带双反斜杠
\\,否则自动加载器无法匹配 - 不要写
"MyOrg\\MyLib\\Http\\": "src/Http/"—— 这会导致Client类被解析为MyOrg\MyLib\Http\Http\Client - 运行
composer dump-autoload生效,无需target-dir
如果非要“把文件放到别的目录”,用 scripts 搞定
比如你发了一个包,希望用户安装后自动把 assets/ 下的 CSS/JS 复制到 public/vendor/mylib/,可以在 composer.json 中加:
{
"scripts": {
"post-install-cmd": [
"cp -r vendor/myorg/mylib/assets public/vendor/mylib"
],
"post-update-cmd": [
"cp -r vendor/myorg/mylib/assets public/vendor/mylib"
]
}
}
注意:
- 这属于副作用操作,不适合核心逻辑,仅适用于静态资源分发
- Windows 用户需用
robocopy或跨平台工具如symfony/filesystem - 路径硬编码风险高,更健壮的做法是写个 PHP 脚本,用
__DIR__动态定位源目录
真正需要控制安装路径的场景极少,多数时候是混淆了「自动加载路径」和「物理安装路径」。盯住 psr-4 映射和 vendor 目录不可变这两条线,就很难走偏。










