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

PHP8下出现未初始化字符串偏移及类型错误的技术求助

PHP 8升级后字符串偏移与类型错误排查解决

错误信息

  1. 警告错误:

Warning: Uninitialized string offset 0 in
错误触发代码行:if($subMenues[$j]['id'] == $permisosMod[$k]['id_sub_menus']){

  1. 致命错误:

Fatal error: Uncaught TypeError: Cannot access offset of type string on string in C:\xampp\htdocs\ebsoftap\Controllers\Setupdashboard.php:29 Stack trace: #0 C:\xampp\htdocs\ebsoftap\Libraries\Core\Load.php(12): Setupdashboard->Setupdashboard('') #1 C:\xampp\htdocs\ebsoftap\Index.php(33): require_once('C:\xampp\htdocs...') #2

问题代码

public function Setupdashboard(){
    $data['page_tag']       = "Configuración - Empresa*";
    $data['page_title']     = "Configuración - Empresa*";
    $data['page_name']      = "setupdashboard";
    $data['permisos']       = $_SESSION['permisos'];
    $data['permisosMod']    = $_SESSION['permisosMod'];
    $data['ThisModulo']     = getModulo(get_class($this));  
    $_SESSION['moduloFull'] = $this->model->selectModulo($data['ThisModulo']);
    $data['menues']         = $this->model->selectMenues($data['ThisModulo']);
    for ($i=0; $i < count($data['menues']); $i++) { 
        $subMenues = $data['menues'][$i]['subMenues'];
        for ($j=0; $j < count((array)$subMenues); $j++) {
            $permisosMod = $data['permisosMod'];
            for ($k=0; $k < count($permisosMod); $k++) { 
                if($subMenues[$j]['id'] == $permisosMod[$k]['id_sub_menus']){
                    $data['menues'][$i]['subMenues'][$j]['r'] = $permisosMod[$k]['r'];
                    $data['menues'][$i]['subMenues'][$j]['w'] = $permisosMod[$k]['w'];
                    $data['menues'][$i]['subMenues'][$j]['u'] = $permisosMod[$k]['u'];
                    $data['menues'][$i]['subMenues'][$j]['d'] = $permisosMod[$k]['d'];
                }
            }
        }
    }
    $data['nav_bar']        = "nav_admin.php";
    $data['page_functions_js']  = "functions_dsetupsdashboard.js";
    $this->views->getView($this,"setupdashboard",$data);
}

问题根源

PHP 8对类型检查的严格性大幅提升:

  • 旧版本PHP中,当$subMenues是字符串(比如空字符串)时,强制转成数组(array)$subMenues会把字符串转为索引数组(例如"test"转为[0 => "test"]),循环访问超出字符串长度的索引只会抛出警告;但PHP 8直接抛出致命TypeError,禁止对字符串使用数组偏移访问。
  • 代码中未对$subMenues、$permisosMod的类型做校验,当数据源返回非数组值时,就会触发错误。

排查与解决方法

1. 前置校验数据类型

在处理子菜单和权限数据前,先确保它们是数组类型,避免非数组值进入循环:

for ($i=0; $i < count($data['menues']); $i++) { 
    $subMenues = $data['menues'][$i]['subMenues'];
    // 校验并修正subMenues类型
    if (!is_array($subMenues)) {
        $subMenues = [];
        $data['menues'][$i]['subMenues'] = $subMenues;
    }
    for ($j=0; $j < count($subMenues); $j++) {
        $permisosMod = $data['permisosMod'];
        // 校验并修正permisosMod类型
        if (!is_array($permisosMod)) {
            $permisosMod = [];
        }
        for ($k=0; $k < count($permisosMod); $k++) { 
            // ... 后续代码
        }
    }
}

2. 增加索引存在性检查

在访问数组偏移前,先确认索引存在,避免未初始化偏移警告:

if (isset($subMenues[$j]['id'], $permisosMod[$k]['id_sub_menus']) 
    && $subMenues[$j]['id'] == $permisosMod[$k]['id_sub_menus']) {
    $data['menues'][$i]['subMenues'][$j]['r'] = $permisosMod[$k]['r'];
    $data['menues'][$i]['subMenues'][$j]['w'] = $permisosMod[$k]['w'];
    $data['menues'][$i]['subMenues'][$j]['u'] = $permisosMod[$k]['u'];
    $data['menues'][$i]['subMenues'][$j]['d'] = $permisosMod[$k]['d'];
}

3. 修正数据源(Model层)

排查selectMenues方法,确保返回的subMenues字段始终为数组类型——当没有子菜单时,返回空数组[]而非空字符串或其他非数组值,从根源解决数据类型不一致问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 05:22:48