Composer需通过根composer.json的repositories配置path类型才能加载同级目录扩展包,路径如"../my-utils"须相对项目根目录,且本地包composer.json的name必须与require中完全一致,否则install会静默跳过。

Composer 能直接加载同级目录里的扩展包,但必须走 repositories 的 path 类型配置,不能靠改 require 或手动复制。路径写错、composer.json 缺失、名字不一致,都会导致 composer install 静默跳过或报 Could not find package。
怎么配 repositories 才让同级目录生效
路径必须相对于项目根目录的 composer.json,同级目录就用 "../my-package" 这种写法。配置要放在根 composer.json 的顶层 repositories 数组里,不是嵌套在 require 或其他字段下:
{
"repositories": [
{
"type": "path",
"url": "../my-utils"
}
],
"require": {
"myorg/utils": "dev-main"
}
}
-
url不能是绝对路径(如/home/user/my-utils),也不能带file://前缀 - 本地包目录(
../my-utils)下必须有合法composer.json,且其中name字段必须和require里写的完全一致(包括 vendor 名,比如"myorg/utils") - 如果本地包没打 Git tag,
version字段建议设为"dev-main"或"dev-master",并在require中显式写"dev-main",否则 Composer 可能忽略
为什么 composer install 不创建符号链接
默认行为取决于系统和配置:Linux/macOS 下通常软链,Windows 默认复制(除非启用开发者模式并以管理员运行)。要强制软链,得在 repositories 条目里加 options:
{
"type": "path",
"url": "../my-utils",
"options": {
"symlink": true
}
}
- 软链生效的前提是本地包
composer.json里已正确定义autoload(如psr-4),否则即使链接成功,类也加载不到 - 修改本地包代码后,不需要重新
install,但若改过composer.json结构(比如增删 autoload 映射),必须运行composer update myorg/utils刷新链接和 autoloader - CI 环境中建议设
"symlink": false,避免权限或文件系统限制
常见错误:明明配了 path 却提示包找不到
根本原因通常是校验失败,Composer 不报具体错误,只跳过该仓库:
-
../my-utils/composer.json文件不存在,或 JSON 语法错误(比如末尾多逗号) - 本地包
name是"my-utils",但require写的是"myorg/utils"—— 必须一字不差 - 版本约束写成
"1.0.0"或"*",而本地包composer.json里version是"dev-main";应统一用"dev-main" - 执行的是
composer install,但本地包第一次引入时,必须先composer update或composer require myorg/utils触发识别逻辑
autoload 怎么映射才让同级包的类可被自动加载
本地包自己的 composer.json 必须定义 autoload,且路径是相对于它自身根目录的。比如 ../my-utils 目录结构如下:
my-utils/ ├── src/ │ └── MyOrg/Utils/Helper.php ├── composer.json
那么它的 composer.json 应含:
{
"name": "myorg/utils",
"autoload": {
"psr-4": {
"MyOrg\Utils\": "src/"
}
}
}
- 项目主
composer.json不需要额外配置 autoload —— Composer 会自动合并所有已安装包的 autoload 规则 - 改完本地包的
autoload后,必须composer update myorg/utils,否则composer dump-autoload不会重新扫描该包 - 别在主项目里用
classmap或files去“绕过”本地包的 autoload,这会导致命名空间冲突或重复加载
最易被忽略的一点:path 仓库的路径校验发生在 composer update 阶段,而不是 install;如果本地包目录临时不可读(比如权限问题、挂载失败),update 会跳过它且不提示,后续 install 就永远装不上——务必在 CI 或部署脚本里加一步验证路径是否存在且可读。


















