composer depends 查不到真正源头,因为它只扫描项目 composer.json 中显式声明的 require-dev,不解析 vendor/ 中包的实际依赖;若 phpunit/phpunit 是被 laravel/sail 等间接引入,则返回空或仅显示 your-project-name。

composer depends phpunit/phpunit 为什么查不到真正源头
它只扫你项目 composer.json 里显式写的 require-dev,不看 vendor 里谁偷偷带了 PHPUnit。比如你没直接 require phpunit/phpunit,但 laravel/sail 或 spatie/laravel-ignition 把它拉进来了,depends 就会返回空——不是没依赖,是它根本没去 vendor 里翻。
常见错误现象:composer depends phpunit/phpunit 没输出,但 vendor/phpunit/phpunit 确实存在;或者输出只有 your-project-name,说明你项目里根本没声明,纯属“被带进来”的。
- 先确认 PHPUnit 是否已安装:
ls vendor/phpunit/phpunit - 如果存在,立刻换用正解命令:
composer why --tree phpunit/phpunit - 如果报错或没输出,说明包未安装(
why --tree要求目标包必须在vendor/下) - 加
--dev参数才查 dev 链路:composer why --tree phpunit/phpunit --dev
断言失效时怎么快速确认 PHPUnit 实际版本
PHPUnit 5.x 和 10.x 的 assertEquals 行为差异极大(比如 strict 类型检查默认开关不同),光看 composer.json 里的 "phpunit/phpunit": "^9.0" 没用,得看真装了哪个版本。
运行:composer show phpunit/phpunit —— 输出的 versions 行才是真实安装版;若显示 9.6.13 却出现 assertArrayHasKey 失效,大概率是上游包(如 laravel/framework)锁死了低版本。
立即学习“PHP免费学习笔记(深入)”;
- 别信
composer.lock里的 version 字段:它可能被手动改过,以vendor/composer/installed.json为准 - 查依赖树时加
--tree看路径:composer show --tree | grep -A3 -B1 "phpunit" - 同一包在树里出现多次,缩进不同 ≠ 装了多份,但得核对各路径下的版本是否一致(
composer show单独查)
composer why-not phpunit/phpunit:^10.0 为什么报“no versions”
这不是 PHPUnit 包本身不存在,而是你的项目约束直接拦死了它——比如 laravel/framework 在 composer.json 里写了 "phpunit/phpunit": "^9.5",Composer 就不会考虑 10.x 的任何版本。
执行:composer why-not phpunit/phpunit:^10.0,它会一层层吐出阻断链,例如:
laravel/framework v10.32.0 requires phpunit/phpunit (^9.5) → spatie/laravel-ignition v2.4.0 requires phpunit/phpunit (^9.0)
注意:why-not 不依赖当前是否已安装该包,只要 composer.json 或 lock 文件里有冲突约束就会触发。
- 必须写完整版本约束:
phpunit/phpunit:^10.0,不能只写phpunit/phpunit - 如果输出为空,检查是否漏了
--dev:某些约束只在require-dev里 - PHP 版本不匹配也会导致“no versions”,运行
php -v对比包要求的php字段
升级 PHPUnit 后断言突然失效,怎么定位是哪个包改了行为
不是所有版本升级都语义化。比如 phpunit/phpunit 从 9.x 升到 10.x,$this->assertEquals('a', 'A', '', false) 的第三个参数(message)在 10.x 被移除,但 Composer 不报错,运行时才抛 Too many arguments。
关键动作不是重装,是比对变更点:
- 运行
composer show --tree phpunit/phpunit,记下旧版和新版的上游包(如laravel/framework)版本 - 对比两次
composer.lock,搜索phpunit/phpunit的version和source.reference(Git commit hash) - 去 GitHub 查对应 tag 的 CHANGELOG:
git diff v9.6.13 v10.5.0 src/Framework/Assert.php - 临时加一行
var_dump(method_exists('PHPUnit\Framework\Assert', 'assertEquals'));排除 autoloader 缓存干扰
最易被忽略的是:vendor/composer/installed.json 是快照,删过 vendor 或切换分支后没重装,它就还是旧的——所有依赖分析都得基于当前真实安装状态,而不是你以为的状态。



















