composer install --no-install --dry-run 是真正离线校验哈希的正确命令,需确保 vendor/ 存在、composer.lock 未被篡改且 php 环境兼容;composer validate 仅检查 json 格式,不验证 shasum。

composer install --dry-run 会报错说找不到包
离线时直接跑 composer install --dry-run 通常失败,因为 Composer 默认仍会尝试访问 Packagist 或配置的仓库,查包元数据和哈希。它不只校验 composer.lock 结构,还默认做远程依赖解析。
真正能离线验证的,是跳过网络请求、只走本地锁文件校验逻辑:
- 确保你已有完整的
vendor/(或至少有composer.lock和已下载的包缓存) - 运行
composer install --no-install --dry-run—— 注意加--no-install,它会跳过解包动作,但保留依赖图构建和哈希比对 - 更稳妥的做法是先用
composer install --no-scripts --no-plugins --no-dev在联网环境预装一次,之后离线时用--ignore-platform-reqs+--no-install组合触发校验
hash 值不匹配却没报错?检查 lock 文件是否被手动改过
composer.lock 里每个包都有 dist.shasum 字段,这是 zip 包解压后内容的 SHA256。Composer 离线校验时,会用这个值对比 vendor/ 下对应包的实际内容。
常见静默失败原因:
- 你删了
vendor/但没删composer.lock,然后离线跑命令——此时没有可比对的文件,Composer 可能只警告不报错 -
composer.lock被编辑器自动转了换行符(CRLF → LF),导致 JSON 解析出错,shasum字段读取失败,校验被跳过 - 用了
composer update但没提交composer.lock,本地 lock 和 vendor 实际不一致,而离线命令又没强制校验完整路径
PHP 版本或扩展不兼容会导致校验中途退出
即使完全离线,Composer 仍会加载 composer.json 中的 platform 配置,并检查当前 PHP 版本、扩展(如 ext-zip)是否满足要求。不满足时,--dry-run 也会直接终止,不输出具体哪条 hash 不对。
排查建议:
- 确认当前 PHP CLI 版本与
composer.json里config.platform.php一致(或更高) - 运行
php -m | grep -E 'zip|json|mbstring',确保基础扩展已启用 - 临时加
--ignore-platform-reqs看是否能走到 hash 校验阶段;如果可以,说明问题出在平台约束,而非 lock 本身
用 composer validate 检查 lock 文件语法只是第一步
composer validate 只校验 composer.lock 是合法 JSON、字段结构符合 schema,**完全不碰 shasum 或 vendor 内容**。它不能告诉你“这个 laravel/framework 的 dist 文件是不是真和 lock 里写的 hash 一致”。
真正有效的离线校验链是:
-
composer validate composer.lock→ 排除格式错误 -
composer install --no-install --dry-run --quiet→ 触发依赖解析 + shasum 比对(需 vendor 存在) - 若报
Invalid package information或Hash mismatch,就定位到具体包名和路径,去vendor/里手动sha256sum对比
别指望一个命令搞定所有事。离线场景下,vendor/ 是否完整、lock 是否干净、PHP 环境是否匹配,三者缺一不可。最容易被忽略的是:你以为删了 vendor 就是“干净离线”,其实 lock 文件里记录的路径和实际缺失的文件之间,根本没有双向校验机制。










