PHP 8.0 正式版发布已有时日,但如果你仍在使用 ThinkPHP 5.1 并计划将项目迁移至 PHP 8.0 运行环境,可能会面临不少兼容性问题:启动时直接报错、函数无法调用、语法弃用警告等等。这些问题本身并不复杂,但需要逐一修复核心文件才能正常运行。下文整理了五个必须处理的修复要点,每个步骤均附带具体文件路径和代码修改示例,按照指引操作即可完成升级。

替换所有 create_function() 调用(PHP 8.0 废弃函数修复)
在 ThinkPHP 5.1 中,create_function() 最常出现在 Cache 类的回调封装逻辑里。PHP 8.0 已经彻底移除此函数,一旦调用即触发 fatal error,无任何兼容余地。
请打开 thinkphp/library/think/Cache.php,全局搜索 create_function,找到类似 create_function('', 'return '.$function.';') 的调用,全部替换为匿名函数:function () use ($function) { return $function; }。
特别提醒:Cache.php 中至少包含 3 处此类调用,任何一处遗漏都将导致缓存模块完全失效,务必逐一替换。
重写 each() 驱动的 while 循环(PHP 8.0 弃用函数迁移)
旧版本 Db.php 和 Model.php 中大量使用 while (list($k, $v) = each($arr)) 进行数组遍历。PHP 8.0 已移除 each() 函数,运行时会直接抛出 Fatal error: Uncaught Error: Call to undefined function each()。
解决方案非常直接:定位到 thinkphp/library/think/Db.php 和 thinkphp/library/think/Model.php,搜索 each(,将所有 while (list($k, $v) = each($data)) { 结构替换为标准的 foreach ($data as $k => $v) { 即可。
此外,如果项目中有自定义继承 Model 的子类且使用了 each(),也必须同步替换——这类代码在 PHP 8.0 下虽不会报错,但会静默跳过循环体,导致数据丢失,排查起来十分棘手。
修复字符串偏移访问语法(PHP 8.0 弃用大括号下标)
PHP 8.0 已废弃 $str{0} 这种字符串偏移写法,而 ThinkPHP 5.1 的 Model.php、Validate.php 等文件中仍保留不少此类代码。虽然目前仅触发 Deprecated 警告,但在特定配置环境下可能中断程序执行,建议彻底清理。
第一步,在项目根目录执行 grep -r "\$\w+\{\d+\}" thinkphp/,定位所有使用 {} 的偏移访问。第二步,将 $value{0} 替换为 strlen($value) ? $value[0] : '',将 $str{1} 替换为 strlen($str) > 1 ? $str[1] : ''。第三步,重点检查 thinkphp/library/think/Model.php 中 getAttr() 方法内的所有字符串下标访问,此处的修复若不到位,将导致字段读取返回 null 或空字符串,数据无法正常获取。
修正 Container 反射类型判断逻辑(PHP 8.0 反射方法变更)
PHP 8.0 调整了 ReflectionParameter::getType() 的行为,其返回值可能为 null,而 ThinkPHP 5.1 的 Container.php 中直接调用 $param->getType()->getName(),缺少判空处理,一旦类型为 null 便会触发 fatal error。
请打开 thinkphp/library/think/Container.php,定位第 466 行附近(具体行号根据版本小幅浮动)。将原代码:
$class = $param->getType()->getName();
替换为:
$type = $param->getType(); $class = $type && !$type->isBuiltin() ? $type->getName() : null;
接下来检查下方 if ($class) 分支内所有对 $class 的使用,确保仅在非 null 时才传入 getObjectParam(),否则同样会导致异常。
处理 mbstring.func_overload 引发的弃用警告(PHP 8.0 配置移除)
此问题不会阻塞应用运行,但会在日志中反复输出警告,严重影响问题排查效率。根本原因在于框架依赖的组件仍尝试读取 PHP 8.0 中已移除的 mbstring.func_overload 配置项。
首先检查服务器 php.ini,确认是否存在 mbstring.func_overload = 0 这一配置——如有,直接注释或删除该行。然后执行 php -i | grep mbstring.func_overload 验证,输出应为空或显示 mbstring.func_overload => no value。
最后,将框架依赖升级至 topthink/framework ≥ v5.1.42,该版本已彻底移除所有对 func_overload 的引用,可一劳永逸解决该警告。
