最直接有效的方法是使用phpcs配合phpcompatibility标准扫描,再用phpstan补漏类型与逻辑问题;因e_deprecated默认不报错、php -l不检测语义废弃,且grep易漏变量调用,而phpcs能精准识别各版本废弃项,phpstan可发现反射等语义级风险。

直接结论:别手动 grep,用 phpcs + PHPCompatibility 扫描最准、最快,再配合 PHPStan 补漏类型和逻辑问题。
为什么不能只靠 error_log 或 php -l 查废弃函数
PHP 的废弃警告(E_DEPRECATED)默认不报错,也不中断执行,仅在错误日志里悄悄写一行;php -l 只校验语法,对 create_function() 这类“语法合法但已被弃用”的函数完全无感。更麻烦的是,有些废弃函数(比如 each())在 PHP 8.0+ 已彻底移除,运行时直接 Fatal error,根本等不到日志出现。
常见错误现象:
- 本地开发环境没报错,上线后 PHP 8.6 容器里脚本直接崩溃
- CI 流程通过,但日志里持续刷出
Deprecated: Function create_function() is deprecated却没人发现 - 用
grep -r "create_function" .漏掉被变量包裹的调用,例如$fn = 'create_function'; $fn(...)
用 phpcs + PHPCompatibility 快速扫描全项目
这是目前最成熟、覆盖最全的命令行方案,能精准识别从 PHP 5.6 到 8.7 各版本中已废弃或已移除的函数、常量、ini 配置项。
实操步骤:
- 全局安装:
composer global require "squizlabs/php_codesniffer=*" "phpcompatibility/php-compatibility=*" - 配置规则路径(关键!否则报
Standard "PHPCompatibility" not found):phpcs --config-set installed_paths ~/.composer/vendor/phpcompatibility/php-compatibility(路径按你实际的composer global安装位置调整) - 扫描整个项目并指定目标版本(例如检查是否兼容 PHP 8.5):
phpcs --standard=PHPCompatibility --runtime-set testVersion 8.5 ./src - 若只想查废弃函数,加过滤:
phpcs --standard=PHPCompatibility --sniffs=PHPCompatibility.FunctionDeclarations.DeprecatedFunctions ./src
注意:testVersion 必须设为你即将升级到的目标版本,不是当前版本。设成 8.5 才会标出 each()、create_function() 等在该版本已移除的调用。
ApiPost是一个支持团队协作,支持模拟POST、GET、PUT等常见请求,并可直接生成文档的API调试、管理工具,ApiPost是后台接口开发者或前端、接口测试人员的工作必备工具。快速生成、一键导出API文档。感兴趣的朋友快来下载吧。软件说明ApiPost官方版是一款十分出色的接口调试与文档生成工具,ApiPost官方版界面美观大方,功能强劲实用,支持团队协作,支持模拟POST、GET、PUT等常见请求,是后台接口开发者或前端、接口测试人员的工作必备工具。软件特色更方便支持接口调试的同时快速生成、一键
PHPStan 补上类型与调用逻辑的盲区
phpcs 能抓“语法级废弃”,但抓不住“语义级风险”。比如 ReflectionProperty::setValue($obj, $val) 在 PHP 8.4+ 已废弃单参数用法,必须显式传 null 设置静态属性——phpcs 不报,但 PHPStan 会提示参数数量不匹配。
推荐命令:
- 安装:
composer require --dev phpstan/phpstan - 运行(Level 8 起开始检查废弃 API 调用):
vendor/bin/phpstan analyse --level=8 src/ - 若想专注废弃项,可加自定义配置,启用
phpstan-deprecation-rules扩展
性能影响:首次全量分析稍慢(尤其大项目),但结果缓存后增量检查很快;它不运行代码,纯静态推导,比开 error_reporting(E_ALL) 跑一遍测试更早暴露问题。
替换时最容易踩的三个坑
自动化工具能定位,但替换逻辑得人来把关。这几个点高频出错:
-
each()不能简单替成key()/current()循环——前者返回带键名/键值的关联数组,后者只是游标操作,while (list($k, $v) = each($arr))必须改用foreach ($arr as $k => $v) -
create_function()替换为闭包时,注意作用域:原函数可访问外部变量靠use,而create_function是字符串 eval,变量捕获行为不同,容易漏传 -
mbereg_*()系列废弃函数(如mbereg_match())没有 1:1 替代,需改用mb_ereg_*()正则函数,但 PCRE 和 MBRegex 引擎行为有差异,必须重测匹配逻辑
真正难的不是找到废弃函数,而是确认每个替换后的语义是否等价——尤其是那些藏在第三方库封装层里、被多次转义或动态拼接的调用。工具扫出来只是起点,逐个验证才是不可跳过的环节。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!










