命令行敲 composer require,报 your requirements could not be resolved,下面列了 php 版本不符和 ext-mbstring 缺失。可 php -v 明明显示 8.1,扩展也在 php.ini 里写着。

composer 走的是哪个 php

composer 本身是个 phar,由某个 php 解释器执行。这个解释器不一定是命令行里的那个。装了多个版本的环境,PATH 里排第一的才是默认。执行 composer 时加 -vvv,开头几行会打印实际的 php 路径和版本号。

另一种情况更隐蔽:composer 是通过 php composer.phar 调的,用哪个版本取决于你敲的是哪个 php。Windows 上还可能是另一个 php.exe 在服务里长期跑着。

明确指定解释器

最稳的写法是不用全局 composer 命令,直接指定。

F:/BtSoft/php/81/php.exe F:/path/composer.phar install
这样版本完全可控,换个项目换一行就行。

Nginx 加 PHP-FPM 的环境,命令行和 FPM 用的是两套配置,ini 也不同。命令行缺扩展时用 php --ini 看加载的是哪个 ini,别对着 FPM 的目录找。

依赖里的 platform 配置

composer.json 里有 config.platform 这一段,可以在本机 PHP 版本和线上不同时,假装成线上的版本做依赖解析。常见写法是声明 php 为 8.0,这样在 8.3 的机器上也能算出线上可用的依赖组合。

反过来,composer install 报锁文件过期,先看 composer.lock 里的 platform 记录,别急着删锁文件重生成,那会把所有依赖升一遍。

CI 上的先后顺序

流水线里经常是先跑 composer,再切换 PHP 版本,顺序反了问题就来了。先切版本,再装扩展,然后才跑 composer install,另外记得 composer 的缓存目录在容器里要单独挂载,否则每次都从零开始下。

排查这类问题记住一句:报错说的是执行 composer 的那个 php,不是你想的那个 php。把路径打出来,问题基本就一目了然了。