内网用Composer必须彻底切断对packagist.org的依赖:实测需在hosts中屏蔽该域名并运行composer install -v,看到Connection refused才算成功;若仍出现Downloading https://repo.packagist.org/packages.json,说明未执行composer config --global repo.packagist false全局禁用默认源。

内网环境用 Composer,不能“连上就用”,必须主动切断对 packagist.org 的默认依赖路径——否则哪怕配了代理或本地源,composer install 仍会卡在 Could not fetch https://repo.packagist.org/packages.json。
怎么确认 Composer 真的不联网了?
别信配置,要实测。临时加一条 127.0.0.1 packagist.org 到 /etc/hosts(Windows 是 %SystemRoot%System32driversetchosts),再跑:composer install -v
看到 Connection refused 或 Failed to connect 才算真正隔离成功。如果还出现 Downloading https://repo.packagist.org/packages.json,说明 repo.packagist 没关干净。
- 必须执行
composer config --global repo.packagist false,全局禁用默认源 - 项目级配置
composer config repository.my-satis composer https://intra.example.com后,要用composer config -l | grep repo验证输出里只剩你的私有源 -
COMPOSER_DISABLE_NETWORK=1是兜底项,不是可选项;它让所有 HTTP 请求直接报错退出,避免插件、脚本或 fallback 机制偷偷联网
artifact 源为什么解压 ZIP 后还是报 “Package not found”?
artifact 不是“放 ZIP 就能用”,它只匹配 composer.lock 中 dist.url 字段的文件名。如果 lock 文件里某包的 dist.url 是 https://example.com/pkg.zip,而你只把同名 ZIP 放进 artifacts/,Composer 会忽略它——因为它没找到 dist.url 对应的本地路径。
- 必须确保外网机器生成 lock 时用了
--prefer-dist,且dist.url是相对路径(如./artifacts/pkg-1.2.3.zip)或file://协议 - 修改
composer.json加 artifact 源后,要删掉旧的vendor/和composer.lock,重新composer update --no-dev --prefer-dist --no-autoloader生成新 lock -
artifacts/必须是相对路径,写成./artifacts/;绝对路径(如/opt/artifacts/)会被 Composer 忽略 - ZIP 文件名必须和 lock 里
dist.shasum对应的原始归档名完全一致,大小写、扩展名、版本号都不能差
Satis 构建完为什么客户端还是找不到包?
Satis 生成的是静态文件,不是服务。客户端报 “Package not found”,90% 是因为 packages.json 根本没被正确访问到,而不是包没镜像全。
- 用
curl -I https://intra.example.com/packages.json验证:状态码必须是200,响应头必须含Content-Type: application/json;302 重定向或 401 会导致 Composer 静默跳过该源 - Satis 构建命令必须带
--skip-errors吗?不。它会让失败包静默消失,你根本不知道缺了啥;应该先不加,逐个修通repositories里的 Git URL 和认证 -
satis.json中的require必须穷举所有直接 + 间接依赖;composer show --tree输出里每一行(包括psr/log这类底层包)都得列进去,漏一个就装不上 - 离线机 PHP 必须能解析 HTTPS 证书:若 Satis 用自签名证书,得把 CA 根证书加进 PHP 的
openssl.cafile,否则 cURL 层失败,Composer 只无限等待,不报错
path 仓库在内网部署时最常翻车在哪?
path 类型看着最简单,但它是唯一会在 vendor/ 下创建软链接(Linux/macOS)或复制(Windows)的仓库类型——这意味着目标机必须能读取那个本地路径,且权限一致。
- path 值写相对路径(如
../my-lib)时,composer install的工作目录必须和composer.json里声明的路径上下文一致,否则解析失败 - Windows 下路径分隔符必须用双反斜杠
\或正斜杠/,单反斜杠会被 PHP 解析为转义字符 - 本地包的
composer.json必须有name和version(或dev-master这类分支名),且composer require vendor/name:dev-main的版本约束必须和它严格匹配 - 不要在生产环境用 path 仓库:它绕过了 dist 归档校验,一旦本地目录被删或权限变更,
autoload.php会直接报Class not found,错误无提示
真正麻烦的从来不是“怎么配”,而是“怎么验证每一步都没走公网”。内网环境里,一个没被注意到的 curl_init() 调用、一个没关掉的插件、甚至 composer.json 里一行注释掉的 packagist 配置,都可能让整个流程卡在不可见的网络请求上。











