
当使用 Composer 本地仓库(如 Satis)时,composer install 仅安装 require/require-dev 中声明的顶层包,却忽略其深层依赖——根本原因在于本地仓库元数据不完整,未正确导出 conflict、replace、provide 等关键字段,导致 Composer 无法解析依赖图谱。
当使用 composer 本地仓库(如 satis)时,`composer install` 仅安装 `require`/`require-dev` 中声明的顶层包,却忽略其深层依赖——根本原因在于本地仓库元数据不完整,未正确导出 `conflict`、`replace`、`provide` 等关键字段,导致 composer 无法解析依赖图谱。
这个问题看似是 Composer 行为异常,实则是本地仓库构建流程中的典型元数据盲区。正如你在 Laravel 9 项目中观察到的:即使本地仓库已托管 laravel/framework、guzzlehttp/guzzle 等 11 个主包,且每个包 ZIP 内含合法 composer.json,composer install 仍报错 Class "Illuminate\Foundation\Application" not found——这并非包缺失,而是 Composer *根本没尝试安装 `illuminate/` 系列依赖**。
原因在于:Satis(或其他 Composer 私有仓库服务)不解析 ZIP 包内的 composer.json,而是完全依赖其生成的 packages.json 元数据文件。该文件必须显式包含每个包的全部“根级(root)字段”,否则 Composer 在依赖求解阶段会视其为“无依赖声明”的裸包,跳过递归解析。
✅ 正确的 satis.json 配置需确保为每个包注入以下关键元数据字段(按实际存在性动态补全):
{
"name": "your-vendor/your-package",
"version": "dev-main",
"require": { "php": "^8.1", "illuminate/support": "^9.0" },
"require-dev": { "phpunit/phpunit": "^9.5" },
"conflict": { "laravel/framework": "<p>⚠️ 常见错误配置(导致依赖丢失):</p><div class="aritcle_card flexRow artxards">
<div class="artcardd flexRow">
<a class="aritcle_card_img" rel="nofollow" href="/xiazai/skill9412" title="Workflow Decomposer"><img
src="https://img.php.cn/upload/skill/001/246/273/6adaf20dee630206.jpg" alt="Workflow Decomposer" onerror="this.onerror='';this.src='/static/lhimages/moren/morentu.png'" ></a>
<div class="aritcle_card_info flexColumn">
<a rel="nofollow" href="/xiazai/skill9412" title="Workflow Decomposer" class="overflowclass">Workflow Decomposer</a>
<p class="overflowclass">工作流任务拆解与模型编排技能。使用场景:(1) 收到复杂工作任务需要拆解为可执行步骤,(2) 需要为不同步骤选择最合适的模型,(3) 需要跟踪工作流进度和模型使用情况,(4) 长时间任务卡住需要问题诊断和解决方案。</p>
</div>
<a rel="nofollow" href="/xiazai/skill9412" title="Workflow Decomposer" class="aritcle_card_btn flexRow flexcenter"><b></b><span>下载</span>
</a>
</div>
</div>
- 仅导出
require和autoload,忽略conflict/replace/provide - 使用静态模板硬编码字段,未对不同包做差异化提取
-
satis.json中未启用"archive": {"skip-dev": true},导致开发分支元数据污染生产包
? 实操建议(以 Satis 为例):
-
动态提取元数据:编写预处理脚本,遍历所有源包目录,用
composer show --no-dev --format=json提取真实字段,过滤空值后注入satis.json; -
强制刷新仓库索引:每次更新后执行
php bin/satis build satis.json web/ --skip-errors,并清空本地 Composer 缓存(composer clear-cache); -
验证元数据完整性:检查生成的
web/packages.json,搜索目标包名,确认require下是否包含illuminate/contracts等子依赖项; -
生产环境双重校验:在 CI 中添加断言脚本,
curl -s http://localhost/packages.json | jq '.packages["laravel/framework"][] | select(.require."illuminate/contracts")',确保关键依赖字段存在。
? 进阶提示:若采用 type: "path" 本地开发(非 Satis),则无需元数据配置——Composer 直接读取本地 composer.json 并实时解析依赖。但私有仓库场景下,元数据即契约,缺失即失效。切勿假设“包文件存在 = 依赖可解析”,务必让 packages.json 成为完整、自洽、可验证的依赖事实源。










