离线时 composer install 卡在二进制下载,因 composer 对 "bin" 字段硬编码自动联网校验;解决需手动放入可执行文件、设 "bin-compat": "full"、删 bin-compat.php、确保 installed.json 和 lock 文件完整。

离线时 composer install 会卡在二进制文件下载(比如 phpunit、larastan、pest 的 phar 或预编译二进制),因为默认行为是每次从 bin-compat 或 bin-links 指向的远程 URL 下载,而不是复用已缓存的二进制。
为什么 composer install --no-scripts 还是会下载二进制?
因为很多包把二进制下载逻辑写在 post-install-cmd 或 post-autoload-dump 脚本里,这些脚本即使加了 --no-scripts,只要 composer.json 里声明了 "bin" 字段,Composer 就会在安装后自动尝试拉取或校验——这是 Composer 本身对 bin 的硬编码行为,不走脚本控制。
-
bin字段声明的路径(如"bin": ["vendor/bin/phpunit"])会触发BinCompilers流程,该流程默认联网检查 hash 和下载 - 即使本地
vendor/bin/phpunit已存在且可执行,Composer 仍可能去请求https://github.com/sebastianbergmann/phpunit/releases/download/...来比对 - 这个行为在
composer v2.5+中更激进,尤其当bin-dir不在默认位置或config.bin-dir被自定义时
离线可用的二进制必须提前“固化”进 vendor 目录
不能依赖缓存或临时复制;必须让 Composer 认为二进制是“已安装完成”的状态。核心是绕过它的自动下载逻辑:
- 手动把目标二进制(如
phpunit-10.5.10.phar)放进vendor/bin/,并确保权限为0755 - 在项目根目录运行
composer dump-autoload,强制刷新 autoload + bin 链接 - 删掉
vendor/composer/bin-compat.php(如果存在),它会干扰离线判断 - 关键一步:在
composer.json的config块中加"bin-compat": "full",并确保没有"bin-dir"覆盖默认值(即保持vendor/bin)
composer install --no-plugins --no-scripts 仍失败?检查这几个点
常见报错像 file_get_contents(https://...): failed to open stream 或 Could not parse version constraint ^10.0: Invalid version string "^10.0"(其实是网络超时导致解析失败),问题往往不在命令参数本身:
- 确认
vendor/composer/installed.json存在且完整——离线时它必须由上一次在线install生成,否则 Composer 会试图重拉元数据 - 检查
composer.lock是否包含dist.shasum字段:没有的话,离线时无法跳过完整性校验,会卡在 hash 请求 - 某些包(如
spatie/binary-parser)会通过require-dev引入带bin的工具,但没显式声明bin,这种要手动补到composer.json的bin数组里,否则 Composer 不识别它是“可执行文件” - Windows 下注意路径分隔符:如果提前复制了二进制,确保
vendor/bin/xxx.bat或.exe文件存在,且composer.json里bin列表包含对应扩展名
真正麻烦的是那些动态生成二进制的包(比如用 roave/security-advisories 配合 composer-unused 时触发的 runtime 编译),它们没法靠“提前放好文件”解决——得在上线前就用相同 PHP 版本+扩展组合,在干净环境中跑一遍完整 install,再把整个 vendor/ 打包带走。










