composer install 仍走 packagist.org 的最常见原因是配置未生效:优先级为命令行 > 项目 composer.json repositories > 全局 config;若项目中仅设 "packagist.org": false 却未配置镜像 url,将回退至官方源;需确认项目内执行 composer config repositories.packagist 和全局 composer config -g repos.packagist 均指向正确镜像地址;使用 create-project 时须显式加 --repository-url;nginx 镜像需全量代理而非静态匹配;satis 同步需在 satis.json 中指定镜像为上游源,并避免 php 8.2+ 兼容问题,推荐改用 toran-proxy 或 packagist-mirror,或直接使用 nexus/artifactory。

composer install 为什么还是走 packagist.org?
本地镜像没生效,最常见原因是 composer.json 或全局配置里没真正切换源。Composer 优先级是:命令行参数 > 当前项目 composer.json 的 repositories > 全局 config(composer config -g repos.packagist)。如果项目里写了 "packagist.org": false 却没配自己的镜像地址,它会 fallback 到官方源。
- 检查是否在项目根目录执行了
composer config repositories.packagist composer <a href="https://www.php.cn/link/5bfe535c8d57f2ecb1d83dd3d83f6a61">https://www.php.cn/link/5bfe535c8d57f2ecb1d83dd3d83f6a61</a> - 确认
composer config -g repos.packagist输出的是你期望的镜像地址,不是{"url": "<a href="https://www.php.cn/link/ec811d0d775adc62776ba80fadd4ed19">https://www.php.cn/link/ec811d0d775adc62776ba80fadd4ed19</a>", "type": "composer"} - 如果用了
composer create-project,它默认忽略本地配置,得加--repository-url=<a href="https://www.php.cn/link/5bfe535c8d57f2ecb1d83dd3d83f6a61">https://www.php.cn/link/5bfe535c8d57f2ecb1d83dd3d83f6a61</a>
用 nginx 搭局域网镜像时,rewrite 规则写错会 404
Packagist 镜像不是简单把文件拷过去就行,它依赖精确的 URL 路由:比如 /packages.json、/p/provider-latest%24a1b2c3.json、/dist/vendor/pkg-hash.zip。nginx 必须把所有请求透传给后端服务(如 Satis、Private Packagist 或自建的 mirror-proxy),不能按静态文件规则匹配。
- 不要写
location / { try_files $uri =404; }—— 这会让/p/xxx.json直接 404 - 正确做法是全量代理:
location / { proxy_pass https://upstream-mirror/; proxy_set_header Host upstream-mirror; } - 如果用 Satis,它生成的
packages.json里含绝对 URL,得用satis.json的config.http-basic和config.notify-batch配合replace重写域名,否则客户端下载 dist 包时仍会连外网
镜像同步失败:satis build 报错 “Could not fetch https://repo.packagist.org/p2/xxx.json”
Satis 默认尝试直连 packagist.org,即使你设了 repositories。它不读 Composer 全局 config,也不走系统代理,必须显式指定上游源为镜像地址。
- 在
satis.json里删掉"packagist.org": false,改用:"repositories": [ { "type": "composer", "url": "https://www.php.cn/link/5bfe535c8d57f2ecb1d83dd3d83f6a61" } ] - 同步时加
--no-interaction --skip-errors,否则单个包失败就中断 - 注意 Satis 会缓存 vendor 包元数据到本地
output/,但不会自动清理过期包。长期运行需定期rm -rf output/p/并重建,否则packages.json体积膨胀、加载变慢
PHP 8.2 下 satis build 报 Deprecated: strlen(): Passing null to parameter #1 ($string) of type string is deprecated
这是 Satis 本身未适配新版 PHP 的典型表现。satis 最后一次发布是 2021 年,已停止维护,PHP 8.1+ 的严格类型提示会让很多地方崩。强行升级 PHP 版本只会暴露更多兼容问题。
- 不要试图用
composer global require composer/satis在新 PHP 上跑 —— 它依赖旧版composer/composer,和现代 Composer 2.5+ 冲突 - 更可行的替代方案是改用
toran-proxy(已归档但代码更健壮)或轻量级packagist-mirror(纯 PHP 脚本,无框架依赖) - 如果非用 Satis,锁定 PHP 7.4–8.0 运行环境,用 Docker 隔离:
docker run --rm -v $(pwd):/app -w /app php:8.0-cli php bin/satis build satis.json web/
镜像服务看似只是换了个 URL,但 Composer 的多层配置优先级、Satis 的静态生成逻辑、PHP 版本与依赖锁死关系,三者叠在一起,任何一个环节松动都会让加速变成幻觉。最省事的方式,其实是直接用公司已有 Nexus 或 Artifactory,它们对 Composer 协议支持更稳,且自带权限和审计。










