phpcompatibility是首选,因其专为php版本迁移设计,覆盖5.0至8.7+所有已知兼容性问题,精准捕获mysql_connect()移除、each()废弃、动态属性警告等rfc级变更,并支持精确版本控制如--runtime-set testversion 8.0或7.4-8.3。

直接用 PHPCompatibility 就够了,它覆盖 PHP 5.0 到 8.7+ 的所有已知兼容性问题,不是“之一”,而是当前事实标准。
为什么 PHPCompatibility 是首选
它不是通用代码风格检查器,而是专为版本迁移设计的静态分析规则集。所有检测点都对应真实 RFC 或官方弃用公告,比如:mysql_connect() 被移除、each() 被废弃、PHP 8.2 中 dynamic properties 默认触发警告、PHP 8.6 中 declare(strict_types=1) 行为收紧——这些都能被精准捕获。
关键优势在于可精确控制目标版本:
-
--runtime-set testVersion 8.0:只报 PHP 8.0 不兼容项 -
--runtime-set testVersion 7.4-8.3:找出在 7.4 到 8.3 全范围都不安全的写法 -
--runtime-set testVersion 8.2-:确保代码能跑在 PHP 8.2 及更高版本
php -l 和 php --syntax-check 只能发现语法错误
它们不检查语义兼容性。例如以下代码在 PHP 7.4 中能通过 php -l,但在 PHP 8.0+ 会 fatal:
function foo(array $a = null) { }
原因:null 不是 array 类型的有效默认值,PHP 8.0+ 强制类型校验。这类问题必须靠 PHPCompatibility 或 PHPStan 检出。
常见误判场景:
- 用
php -l验证后就认为“代码没问题”,结果上线遇到Fatal error: Uncaught TypeError - 把
phpcs配置成通用 PSR-12 规则,漏掉--standard=PHPCompatibility,等于没做兼容性检查
配合 PHPStan 做类型级兼容验证
PHPCompatibility 查“能不能跑”,PHPStan 查“跑起来会不会错”。尤其在 PHP 8.6+ 后者更重要——因为严格类型已成默认行为。
示例:这个函数在 PHP 8.6 下会直接报错,但 PHPCompatibility 不报(语法合法),PHPStan level 8+ 会标记:
function add(int $a, int $b): int { return $a + $b; }
add(1.5, 2); // TypeError: int expected, float given
建议配置组合:
- CI 流程中先跑
phpcs --standard=PHPCompatibility --runtime-set testVersion 8.6 - 再跑
phpstan analyse --level=8 - 两者都通过,才代表真正适配 PHP 8.6+
别依赖 composer check-platform-reqs 判断运行时兼容性
它只检查 composer.json 里写的 "php": "^8.0" 这类声明,不扫描实际代码。你完全可以写 "php": "^8.0",但代码里满篇 mysql_query() ——check-platform-reqs 完全不会报错。
真正要防的,是那些“声明支持 PHP 8.x”但内部用了已被移除 API 的第三方包。这时得靠:
-
PHPCompatibility扫 vendor 目录(加--extensions=php和排除测试文件) - 或用
roave/better-reflection配合自定义规则做深度依赖分析
最常被忽略的一点:PHP 8.7 的 JIT 编译器改动会影响某些扩展的内存访问模式,仅靠静态检查无法覆盖。必须在真实 php:8.7-cli 容器里跑一遍单元测试,观察 segfault 或 zend_mm_heap corrupted 类错误。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











