xdebug 3.x 中 xdebug.mode=debug 和 coverage 不能同时生效,必须分两次运行:调试用 debug 模式,覆盖率分析用 coverage 模式;混用会导致覆盖率为空或调试失败,因 xdebug 启动时仅初始化 mode 列表首个功能。

直接说结论:Xdebug 3.x 的 xdebug.mode=coverage 和 xdebug.mode=debug 不能同时生效,必须分两次运行 —— 调试用一次,覆盖率分析用另一次。混用会导致覆盖率数据为空或调试连接失败。
为什么 coverage 和 debug 不能共存
Xdebug 3 将功能拆分为独立 mode(debug、coverage、profile 等),同一请求只能启用一种 mode。PHP 进程启动时,Xdebug 根据 xdebug.mode 初始化对应子系统;若设为 debug,coverage,实际只加载第一个(debug),coverage 部分完全不工作。
- 现象:运行
phpunit --coverage-html后报告全是灰色/空白,index.html中无高亮行 - 根本原因:CLI 下 PHPUnit 启动的 PHP 进程未进入 coverage mode,
xdebug_start_code_coverage()未被调用 - 验证方式:在命令行执行
php -v | grep xdebug,再加php --ri xdebug | grep mode,确认当前生效 mode
生成有效覆盖率 HTML 报告的实操步骤
确保你用的是 Xdebug 3.1+(php --ri xdebug 查版本),且 php.ini 中已禁用旧式配置(如 xdebug.remote_enable)。
- 修改
php.ini:xdebug.mode=coverage(仅此一项,不要加逗号其他值) - 重启 PHP CLI(非 Apache/FPM):Linux/macOS 执行
phpbrew switch或重载 php-fpm;Windows 用 phpstudy 需重启「PHP 服务」而非仅 Web 服务 - 运行命令:
phpunit --coverage-html ./coverage --whitelist ./src/(注意:不是--coverage-clover,后者不生成 HTML 视图) - 打开
./coverage/index.html,点击文件后观察:红色 = 该行未执行;黄色 = if/else 中仅一个分支命中(例如只走了true,false分支没测)
PhpStorm 中正确配置调试(debug mode)
覆盖率和调试必须分开配,调试阶段要切回 debug mode,否则断点不生效。
-
php.ini改为:xdebug.mode=debug+xdebug.start_with_request=trigger(推荐,避免每次请求都连 IDE) - IDE 中:File → Settings → PHP → Debug → Xdebug → Port 设为
9003(Xdebug 3 默认端口,不是旧版 9000) - 浏览器装
Xdebug Helper插件,设置 IDE Key 为PHPSTORM(需与php.ini中xdebug.idekey一致) - PhpStorm 点击右上角电话图标(Start Listening for PHP Debug Connections),再访问带
?XDEBUG_TRIGGER=1的 URL,才会弹出「Accept Connection」提示
容易被忽略的关键细节
很多人卡在「覆盖率报告没数据」或「断点一直不触发」,问题往往不在配置本身,而在环境切换和进程隔离上。
- CLI 和 Web SAPI 使用不同 php.ini:用
php --ini确认 CLI 加载的是哪个 ini;用phpinfo()页面确认 Web 端加载的是哪个 —— 二者必须分别配对mode - PhpStorm 的「PHP Language Level」要 ≥ 项目所用 PHP 版本,否则某些新语法(如 match 表达式)的分支覆盖会漏报
- PCOV 可作为替代方案:它不依赖 Xdebug,
pcov.enabled=1后可与debug共存,但仅支持行覆盖,不支持分支级(即无法标黄 if 的未执行分支)
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











