最准最快的方式是用 composer show -i vendor/package --path 输出绝对路径,如 monolog/monolog 返回 /var/www/myapp/vendor/monolog/monolog;--path 必须与 -i 同用,包名须全小写且带 vendor,未安装则报错或为空。

composer show -i vendor/package --path 直接输出绝对路径
这是最准、最快的方式,不依赖目录结构或配置猜测。只要包已安装,命令就返回真实路径,比如 composer show -i monolog/monolog --path 输出 /var/www/myapp/vendor/monolog/monolog。
注意三点:
-
--path必须和-i(即--installed)一起用;单独composer show monolog/monolog --path会报错或无输出 - 包名必须全小写、带 vendor,
composer show -i Monolog/Monolog --path会失败 - 如果返回空或报
Package not found,说明该包根本没装进当前项目(可能只在全局、或被 require-dev 排除、或 lock 文件未生效)
查 vendor/composer/installed.json 里的 install-path 字段
这个文件是 Composer 安装后生成的“事实快照”,所有已安装包的路径都记录在 install-path 字段里,比拼接 vendor/ + 包名更可靠——因为 vendor-dir 可能被自定义过,也可能用了 composer/installers 插件(如 WordPress 插件被装到 wp-content/plugins/)。
操作建议:
- 用
jq '.[] | select(.name == "monolog/monolog") | .install-path'快速提取(需安装 jq) - 若不用工具,直接
grep -A5 '"monolog/monolog"' vendor/composer/installed.json找对应块 - 注意:该文件内容是运行时状态,
composer install后才更新,composer require后未执行 install 不会写入
为什么不能直接 ls vendor/vendor/name?
硬拼路径看似简单,但容易误判,尤其在以下场景:
- 项目设置了
"config": {"vendor-dir": "lib/vendor"},此时vendor/根本不存在 - 用了
composer/installers,比如yiisoft/yii2默认装到lib/yii2,而非vendor/yiisoft/yii2 - path 类型依赖是符号链接,但链接目标可能被误删或权限不足,
ls -la看起来存在,实际class_exists()会失败 - Docker 或 CI 环境中,
vendor/可能挂载为 volume,本地ls看不到真实结构
全局包路径要分两层查:vendor-dir 和 bin-dir
全局安装的包(如 phpunit/phpunit)源码和可执行文件不在同一层:
- 源码位置:运行
composer config --global vendor-dir,得到类似/home/alex/.composer/vendor,再拼上包名,如/home/alex/.composer/vendor/phpunit/phpunit - 命令位置:运行
composer global config bin-dir --absolute,得到/home/alex/.composer/vendor/bin,里面是phpunit脚本,它最终调用源码里的入口文件 - 别混淆
composer global show和composer show -i:前者只列全局包,后者只查当前项目,跨环境查错对象是常见疏漏
路径不是静态字符串,而是 Composer 运行时解析出的状态。想确认一个包“真正在哪”,永远优先信 composer show -i --path 或 installed.json,而不是人脑拼接。











