PHP函数getChildOfParentUser报错:Undefined variable $family问题排查
咱们先看系统给出的报错信息:
Notice: Undefined variable: family in /var/www/html/Family.php on line 59
Notice: Trying to get property 'id' of non-object in /var/www/html/Family.php on line 59
Notice: Undefined variable: family in /var/www/html/Family.php on line 62
Notice: Trying to get property 'id' of non-object in /var/www/html/Family.php on line 62
这些提示已经把问题说得明明白白:你在getChildOfParentUser函数里直接用了$family变量,但这个变量在函数内部根本没定义,而且还有其他逻辑错误,咱们一步步拆解修复:
1. 函数参数的错误使用
你的getChildOfParentUser明明接收了$parentId参数,结果第一行就把它覆盖成$family->id——$family是哪里来的?这个变量只在getRootUser的循环里存在,在getChildOfParentUser里完全是未定义的,这是第一个致命错误。
2. SQL查询逻辑搞反了
你写的SQL是SELECT ... WHERE id = $parentId,但你的需求是获取某个父节点的子节点,正确的条件应该是WHERE parent = $parentId啊!你现在查的是ID等于父ID的节点,根本不是子节点,逻辑完全错了。
3. PDO预处理的错误用法
你用了bindValue('id', $family->id),但你的SQL里根本没有:id这种命名占位符,而是直接拼接了变量,这既没用到预处理的优势(防注入),还又一次用到了未定义的$family变量,雪上加霜。
修复后的完整代码
先修正getRootUser(补全缺失的HTML闭合标签,保证结构正确)
public function getRootUser() { $query = "SELECT id, nameOfPerson, parent FROM person WHERE parent is null"; $statement = $this->db->prepare($query); $statement->execute(); echo '<ul id ="family">'; while($family = $statement->fetch(PDO::FETCH_OBJ)){ echo '<li>' . $family->nameOfPerson; // 调用子节点函数,传入当前根节点的ID作为父ID $this->getChildOfParentUser($family->id); echo '</li>'; // 补上之前漏掉的闭合标签 } echo '</ul>'; // 补上外层ul的闭合标签 }
再修正getChildOfParentUser函数
public function getChildOfParentUser($parentId) { // 修正SQL:查询parent等于传入的$parentId的所有子节点 $query1 = "SELECT id, nameOfPerson, parent FROM person WHERE parent = :parentId"; $statement1 = $this->db->prepare($query1); // 正确绑定命名占位符,指定参数类型为整数更安全 $statement1->bindValue(':parentId', $parentId, PDO::PARAM_INT); $statement1->execute(); if($statement1->rowCount() > 0){ echo '<ul>'; while($family2 = $statement1->fetch(PDO::FETCH_OBJ)){ echo '<li>' . $family2->nameOfPerson; // 递归调用,继续查询当前子节点的子节点,实现多层树形结构 $this->getChildOfParentUser($family2->id); echo '</li>'; } echo '</ul>'; } }
修复要点总结
- 删掉了
$parentId = $family->id这行完全错误的代码,直接使用函数传入的$parentId参数 - 把SQL查询条件改成
WHERE parent = :parentId,终于符合“获取子节点”的需求 - 用PDO的命名占位符正确绑定参数,既解决了变量未定义问题,又避免了SQL注入风险
- 补全了
getRootUser里缺失的HTML闭合标签,保证页面结构不会乱 - 添加了递归调用,这样可以渲染出多层级的树形结构(比如你的数据里John→Michel→Husam→Khalaf/Mark这样的完整层级)
这样修改后,你的函数就能正常工作,正确输出整个家庭树的结构了。
内容的提问来源于stack exchange,提问作者Second View

