答案是config.platform.php配置干扰导致Composer误判PHP版本;需运行composer show --platform确认其“认为”的版本,删除或修正composer.json中硬编码的platform.php值,并执行composer update --lock更新锁文件。

composer install 报 “requires php ^8.1” 但 php -v 是 8.2
这几乎肯定不是 PHP 版本问题,而是 config.platform.php 在干扰。Composer 优先读这个配置,而不是你终端里真实的 php -v 输出。
先运行 composer show --platform 看它“认为”的 PHP 版本是多少。如果输出是 php: 7.4.33,哪怕你本地是 8.2,它也会按旧版本解析依赖树,从而选到不兼容的包版本。
- 检查
composer.json里是否有"config": {"platform": {"php": "7.4.33"}}这类硬编码 —— 有就删掉,或改成匹配你真实版本的值(如"php": "8.2.10") - 改完必须执行
composer update --lock,否则composer.lock还记着旧平台信息,下次install仍会复现偏差 - 别用
--ignore-platform-req=php长期绕过 —— 它只跳过校验,vendor 里照样装进 PHP 8.2+ 才能跑的代码,一运行就ParseError: unexpected token "readonly"
为什么 composer update 突然装不上新版本了
不是 Composer 变了,是依赖包自己升级了 PHP 要求。比如 guzzlehttp/guzzle 从 7.5 升到 7.6 后,把 "php": "^7.2.5 || ^8.0" 改成了 "php": "^7.2.5 || ^8.1",你的 PHP 8.0 就被拒绝了。
查清楚谁在拉这个高要求版本:composer depends --tree guzzlehttp/guzzle,看哪条路径触发了约束收紧;再用 composer why-not guzzlehttp/guzzle:^7.6 确认阻断源头。
立即学习“PHP免费学习笔记(深入)”;
- 临时降级:在
composer.json的require里写死兼容版本,如"guzzlehttp/guzzle": "7.5.1"(注意别用~7.5.0,它仍可能升到 7.5.x 最新版) - 慎用
--with-all-dependencies—— 它会强制升级所有子依赖,可能把原本安静的symfony/polyfill也推到不带安全补丁的旧版 - 运行
composer update --dry-run -v看 verbose 日志末尾,常能直接看到冲突点在哪条依赖链上
Alpine Docker 里 composer 显示的 PHP 版本和 php -v 不一致
这不是环境没切对,而是 apk add composer 悄悄装了个独立的 PHP 解释器(比如 8.0.14),和你基础镜像里的 /usr/local/bin/php(8.1.1)打架。Composer 执行时调用了那个旧版,所以报错说“你只有 8.0.14”。
验证方式:运行 which php 和 php -v 必须在同一 shell 里执行,且路径要对得上;再跑 composer check-platform-reqs | grep php 看它实际用了哪个解释器。
- 根本解法:删掉
apk add composer,改用官方 PHAR 方式安装 ——curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer - 确保
PATH中/usr/local/bin在/usr/bin前面,避免系统自带的旧版 PHP 被优先调用 - CI/CD 流水线里如果用了
config.platform.php,值必须和生产环境完全一致,且要配合composer install --no-dev使用
composer show --tree 显示的依赖版本和 Packagist 页面不一致
不是数据错了,是 Composer 默认用本地缓存的 packages.json 元数据算依赖,而这个缓存默认 15 分钟不过期。你看到的可能是旧快照。
比如你知道 monolog/monolog 已发布 3.6.0,但 composer show monolog/monolog --all 只列出到 3.5.0 —— 这说明缓存没刷新。
- 确认镜像是否生效:
composer config -g repo.packagist,输出必须是你配置的镜像地址(如https://mirrors.aliyun.com/composer/) - 执行
composer update --refresh(仅 Composer ≥2.5 支持)—— 它只清元数据缓存,不删已下载的 ZIP 包,快且精准 - 别用
composer clear-cache—— 它连 dist 包都删了,下次 install 又得重下,反而拖慢流程
最易被忽略的一点:删 composer.lock 不是修复手段,是重置。它会让 Composer 从头解析整个依赖图,原本稳定的子依赖(比如某个带安全补丁的 symfony/polyfill)可能被替换成未测试过的旧版,风险远大于表面看起来的“干净重启”。



















