PHP递归函数实现家族谱系查询:如何避免使用全局变量
解决方案
方案1:使用引用参数传递结果数组
给函数增加一个引用类型的可选参数,所有递归调用都操作同一个数组实例,完全避免全局变量污染。
function checkForChildren($uuid, $conn, &$familyArray = []){ $sql = "SELECT id, uuid, name FROM people WHERE parent = '".$uuid."'"; $result = mysqli_query($conn, $sql); if (mysqli_num_rows($result) > 0){ foreach ($result as $row){ $familyArray[]= [ 'id' => $row['id'], 'uuid' => $row['uuid'], 'name' => $row['name'] ]; checkForChildren($row['uuid'], $conn, $familyArray); } } return $familyArray; }
调用时不需要传第三个参数,函数会自动初始化空数组:$allDescendants = checkForChildren('0001', $conn);
方案2:纯函数实现(无引用、无额外参数)
每次递归调用返回当前节点的所有后代数组,把当前层级的子节点和子节点的递归结果合并后返回,完全无外部依赖,无副作用。
function checkForChildren($uuid, $conn){ $familyArray = []; $sql = "SELECT id, uuid, name FROM people WHERE parent = '".$uuid."'"; $result = mysqli_query($conn, $sql); if (mysqli_num_rows($result) > 0){ foreach ($result as $row){ // 先加入当前层级的子节点 $familyArray[]= [ 'id' => $row['id'], 'uuid' => $row['uuid'], 'name' => $row['name'] ]; // 合并当前子节点的所有后代 $familyArray = array_merge($familyArray, checkForChildren($row['uuid'], $conn)); } } return $familyArray; }
额外优化建议
- 现有SQL直接拼接UUID参数存在SQL注入风险,建议改为mysqli预处理语句查询,示例如下:
$stmt = mysqli_prepare($conn, "SELECT id, uuid, name FROM people WHERE parent = ?"); mysqli_stmt_bind_param($stmt, "s", $uuid); mysqli_stmt_execute($stmt); $result = mysqli_stmt_get_result($stmt);
- 如果数据量较大,递归查询会产生多次数据库请求,性能较低,可以考虑一次性查询全表后在PHP内存中构建树结构再提取后代,减少数据库IO开销。
内容的提问来源于stack exchange,提问作者DivFellaPoor
相关产品推荐
相关产品推荐

