You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

升级PHP8报Cannot access offset of type string on string错误修复

问题背景
  • 运行环境升级至PHP 8版本后,触发致命错误:Uncaught TypeError: Cannot access offset of type string on string
  • 错误定位代码行:if(is_array($course_data['steps']['h']["sfwd-lessons"])){
  • 代码用于提取LearnDash插件的课程步骤数据,在低版本PHP环境中可正常运行,原业务代码如下:
// bail out if this is not an event item
    if ('sfwd-courses' !== get_post_type($post_id)) {
        return;
    }
    $course_data  = get_post_meta($post_id, 'ld_course_steps', true);
    if (!empty($course_data)) {
        $lessons = array_keys($course_data['steps']['h']["sfwd-lessons"]);
        $quizes = array_keys($course_data['steps']['h']["sfwd-quiz"]);
    }

$lesson_data = [];
    // Extract all steps of the courses
    if(is_array($course_data['steps']['h']["sfwd-lessons"])){
        foreach($course_data['steps']['h']["sfwd-lessons"] as $lesson){
            $lesson_data = array_merge($lesson_data,array_values(array_keys($lesson["sfwd-topic"])));
            $lesson_data = array_merge($lesson_data,array_values(array_keys($lesson["sfwd-quiz"])));
            foreach($lesson["sfwd-topic"] as $topic){
                $lesson_data = array_merge($lesson_data,array_values(array_keys($topic["sfwd-quiz"])));
            }
        }
    }
报错原因

问题由PHP版本语法规则调整、代码缺少多层结构合法性校验共同导致:

  • PHP 7.x及更早版本中,对字符串等非数组类型的值使用数组方括号语法访问偏移量时,仅抛出非致命的Notice/Warning级提示,不会中断执行,此时访问返回null,后续is_array(null)结果为false,逻辑自动跳过分支,表面上运行正常。
  • PHP 8.0起,这类非法操作被升级为致命TypeError,程序会直接终止运行,不再兼容非数组类型的数组式访问写法。
  • 代码逻辑缺陷:仅判断了$course_data非空,没有校验$course_data['steps']、$course_data['steps']['h']是否为数组。一旦数据库中存储的ld_course_steps元数据存在格式损坏、旧版本数据结构不匹配、返回值为非数组类型的情况,链式访问多层数组下标就会触发报错。
修复方案

核心修复逻辑为:在访问每一层数组下标前,先校验对应层级的值为数组、且目标键存在,避免对非数组值执行数组式访问,同时补全变量初始化避免未定义变量警告。修复后完整代码如下:

// bail out if this is not an event item
if ('sfwd-courses' !== get_post_type($post_id)) {
    return;
}
$course_data  = get_post_meta($post_id, 'ld_course_steps', true);
// 初始化变量避免未定义告警
$lessons = [];
$quizes = [];
$lesson_data = [];

// 逐层校验数组结构合法性
if (
    is_array($course_data)
    && isset($course_data['steps']['h'])
    && is_array($course_data['steps']['h'])
) {
    $steps_h = $course_data['steps']['h'];
    // 校验课程列表键存在且为数组再取值
    if (isset($steps_h["sfwd-lessons"]) && is_array($steps_h["sfwd-lessons"])) {
        $lessons = array_keys($steps_h["sfwd-lessons"]);
    }
    // 校验测验列表键存在且为数组再取值
    if (isset($steps_h["sfwd-quiz"]) && is_array($steps_h["sfwd-quiz"])) {
        $quizes = array_keys($steps_h["sfwd-quiz"]);
    }

    // 提取课程下所有关联步骤
    if(isset($steps_h["sfwd-lessons"]) && is_array($steps_h["sfwd-lessons"])){
        foreach($steps_h["sfwd-lessons"] as $lesson){
            // 校验课时下的主题结构
            if (isset($lesson["sfwd-topic"]) && is_array($lesson["sfwd-topic"])) {
                $lesson_data = array_merge($lesson_data, array_values(array_keys($lesson["sfwd-topic"])));
                foreach($lesson["sfwd-topic"] as $topic){
                    // 校验主题下的测验结构
                    if (isset($topic["sfwd-quiz"]) && is_array($topic["sfwd-quiz"])) {
                        $lesson_data = array_merge($lesson_data, array_values(array_keys($topic["sfwd-quiz"])));
                    }
                }
            }
            // 校验课时下的测验结构
            if (isset($lesson["sfwd-quiz"]) && is_array($lesson["sfwd-quiz"])) {
                $lesson_data = array_merge($lesson_data, array_values(array_keys($lesson["sfwd-quiz"])));
            }
        }
    }
}

修复点说明:

  • 提前初始化$lessons、$quizes变量,避免数据结构不符合预期时出现变量未定义的警告
  • 从最外层$course_data开始逐层做类型校验和键存在判断,所有数组下标访问都在确认前序值为数组的前提下执行,完全适配PHP 8的语法规则
  • 对循环内部的$lesson、$topic层级也补充了类型校验,避免遍历过程中出现同类类型错误
  • 提取重复访问的$steps_h变量减少重复的数组层级访问,性能略有提升

内容的提问来源于stack exchange,提问作者Ilianskia

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.27 19:42:14