PHP USSD菜单无法显示,Undefined offset等报错修复求助
修复PHP USSD菜单显示报错的解决方案
错误根源分析
- Undefined offset: 3:
recurseMenu的循环未校验索引范围,当$bufferLimit大于菜单条目总数时,会访问$items中不存在的索引 - Undefined index:
getNode方法直接访问$treeMenu[$name],未判断目标索引是否存在 - Call to a member function getTitle() on null:未检查
getNode返回的节点是否有效,直接调用方法导致致命错误 - 隐藏问题:
toString方法中字符串长度判断存在语法错误,导致循环逻辑失效
分步修复代码
1. 修复UssdTree.php的getNode方法
增加索引存在性校验,避免直接访问不存在的键:
function getNode($name){ return isset($this->treeMenu[$name]) ? $this->treeMenu[$name] : null; }
2. 修复UssdNode.php的recurseMenu方法
增加索引越界、会话有效性、节点有效性的多重校验:
function recurseMenu($items,$bufferLimit) { $objectString="<strong>". $this->getTitle() . "</strong>" . PHP_EOL; $lastMenu=false; $itemsCount = count($items); if($itemsCount>0) { // 计算安全的循环上限,避免越界 $maxIndex = min($bufferLimit, $itemsCount); for($i=$this->index;$i<$maxIndex;$i++){ if(!isset($items[$i])) continue; $item=$items[$i]; $num=$i+1; // 校验会话有效性 if(!isset($_SESSION['userSessions'][$this->address])) { $title = "Invalid Session"; } else { $currUserSession=$_SESSION['userSessions'][$this->address]; $node=$currUserSession->getNode($item); // 校验节点有效性 $title = $node ? $node->getTitle() : "Invalid Menu Item"; } $objectString=$objectString . PHP_EOL .$num . '. ' .$title; } } else { $objectString=$objectString.PHP_EOL . 'NO DATA AVAILABLE, TRY AGAIN LATER'; } // 修正最后一页判断逻辑 $lastMenu=$bufferLimit>=$itemsCount; $objectString=$objectString . PHP_EOL . PHP_EOL . "<strong>0. Exit</strong>"; if($this->getParent() != '0'){ $objectString=$objectString . PHP_EOL . "<strong>#. Back</strong>"; } if($lastMenu===false){ $rem=$itemsCount-$this->index; $objectString=$objectString . PHP_EOL . "<strong>99. Next (" .$rem.")</strong>"; } return $objectString; }
3. 修复UssdNode.php的toString方法
修正字符串长度判断的语法错误:
function toString(){ $objectString=''; $items=$this->children; $itemsCount = count($items); $bufferLimit=$itemsCount==0 ? 1 : $this->getBufferLimit()+1; // 移除调试输出(如需保留请注释) // echo "<pre>"; // print_r($this->recurseMenu($items,$bufferLimit)); // echo "</pre>"; // 修正循环条件的语法错误 do{ $bufferLimit-=1; $objectString=$this->recurseMenu($items,$bufferLimit); }while(strlen($objectString) > 160); $this->index=$bufferLimit; return $objectString; }
修复效果
- 消除所有Notice和Fatal错误
- 菜单条目会正常显示,无效项会被替换为提示文本
- 确保USSD内容长度符合160字符限制
- 循环逻辑不会再出现越界访问问题
内容的提问来源于stack exchange,提问作者user19778377
相关产品推荐
相关产品推荐

