应提交 composer.lock,但须按可运行项目粒度单独管理;纯库禁用 lock 文件,根目录设为 metapackage;path 仓库需显式配置并注意软链接与 autoload 问题。

Monorepo里该不该提交 composer.lock
应该提交,但必须按项目粒度分别管理——不是整个仓库一个 composer.lock,也不是每个包都各自提交一份。
常见错误是把根目录的 composer.lock 当作“全局锁”,结果导致子包依赖版本不一致、CI 构建结果漂移;另一种极端是每个 package/xxx 下都放一个 composer.lock,但又没配 "type": "project",导致 composer install 拒绝生效。
- 只有明确为可运行项目(如 CLI 工具、API 服务)的子目录才需要自己的
composer.lock - 纯 PHP 库(
"type": "library")不许有composer.lock,它靠根composer.json的require约束和 CI 中的composer update --lock保证一致性 - 根目录的
composer.json必须设"type": "metapackage"或干脆不设type,避免 Composer 尝试安装它
子项目执行 composer install 报错 “Package not found”
本质是 Composer 默认只读当前目录的 composer.json,完全不知道你这个 Monorepo 里还有其他本地包。
解决方式不是改 repositories 类型,而是用 path 类型 + 通配符,且必须启用 composer config --global repositories.packages.path packages/* 这类配置——但更稳妥的是在每个子项目的 composer.json 里显式声明:
{
"repositories": [
{
"type": "path",
"url": "../../packages/*"
}
]
}
注意:path 仓库不支持版本约束(如 ^1.2),只能靠目录名或 version 字段匹配;若子包 composer.json 里写了 "version": "dev-main",那依赖方就得写 "my/package": "dev-main",不能写 "dev-main as 1.0.0"——后者会绕过 path 加载逻辑。
围绕关键发现、作用机制、临床相关性及研究局限性展开讨论。适用于撰写或优化任何生物医学论文的“讨论(Discussion)”部分——包括结果解读、与既往文献关联、阐释意外发现、界定研究局限性,以及撰写结论。当用户输入以下任一指令时也会自动触发该功能: - “write my discussion” - “help me discuss my findings” - “how do I compare to prior studies” - “write the limitations par
composer update 在 Monorepo 中更新范围失控
默认执行 composer update 会尝试更新所有依赖,包括你根本不想动的本地 path 包,极易引发意外版本覆盖或符号链接断裂。
- 永远用
composer update --no-install先生成新锁,再人工检查 diff - 更新指定包时,务必加
--with-all-dependencies,否则可能只更新顶层包,留下不兼容的子依赖 - 本地
path包的变更,应先git commit,再在依赖方执行composer update vendor/name,而不是直接composer update - CI 中建议统一用
composer install --no-interaction --prefer-dist,禁用update步骤
PHP 8.2+ 和 Composer 2.5+ 下 path 仓库的符号链接行为变化
Composer 2.4 之前,path 包默认创建硬链接;2.5+ 改为软链接(symlink),且 PHP 8.2 默认禁用 follow_symlinks,导致 class_exists() 或自动加载失败。
这不是 bug,是安全策略收紧。绕过方法极有限:
- 开发环境可在
php.ini加opcache.enable_cli=0(仅限 CLI) - 更可靠的是在子项目
composer.json中加"autoload": {"psr-4": {"My\Ns\": "src/"}}并确保路径真实存在,而非依赖 symlink 后的映射 - CI 构建中,用
composer install --no-scripts避开 autoload 生成阶段,后续手动跑composer dump-autoload
最麻烦但最稳的方式:放弃 path,改用 artifact 仓库 + 本地 tarball,适合对稳定性要求极高的场景。不过这意味着每次改本地包都要手动打包,节奏卡得死。










