PHP实现无限级上级ID回溯与树形分类递归

竹里
竹里
发布时间:2026-10-15| 3人浏览过
原创

在处理具有层级关系的数据时,PHP开发常需处理两种场景:根据子节点反向追溯所有父节点ID,或将扁平列表转换为树形结构以展示分类。本文将分别针对这两种情况提供基于递归的高效解决方案,涵盖数据库字段设计、核心函数逻辑及实际调用方式。

场景一:递归获取无限上级ID

当数据表采用自引用结构(如 auth_id 指向父级ID)且需要获取某个节点的所有祖先ID时,可通过SQL查询结合PHP递归实现。此方法适用于权限链、组织架构图等需要向上追溯的业务场景。

准备条件:数据库结构设计

首先,确保表中存在指向父级的字段。例如 fcxlt_authuser 表中,id 为主键,auth_id 存储上级用户的ID。递归的终止条件通常设定为 ID=1(根节点)或特定标识。

CREATE TABLE `fcxlt_authuser` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `username` varchar(50) NOT NULL COMMENT '用户名',
  `password` varchar(64) NOT NULL COMMENT '密码',
  `nickname` varchar(50) NOT NULL COMMENT '昵称',
  `phone` varchar(20) DEFAULT NULL COMMENT '电话',
  `weixin_id` varchar(20) DEFAULT NULL COMMENT '微信号',
  `qrcode` varchar(200) DEFAULT NULL COMMENT '二维码Base64',
  `auth_id` int(11) NOT NULL COMMENT '上级用户ID',
  `is_authed` int(11) NOT NULL,
  `createtime` int(11) NOT NULL DEFAULT '1523156898',
  PRIMARY KEY (`id`),
  KEY `nickname` (`nickname`),
  KEY `auth_id` (`auth_id`,`id`,`username`,`nickname`) USING BTREE,
  KEY `username` (`username`,`is_authed`,`password`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=103 DEFAULT CHARSET=utf8mb4;

第1步:编写递归追溯函数

创建一个递归方法,每次查询当前节点的 auth_id,并将该ID追加到结果字符串中,直到遇到根节点。注意:必须在递归调用处使用 return,否则函数可能返回 NULL 导致逻辑中断。

public function getWinfo($id, $res = '') {
    // 假设ID大于1表示非根节点,可根据实际需求调整终止条件
    if ($id > 1) {
        $infos = Db::name('authuser')
            ->alias('a')
            ->where('a.id', $id)
            ->join('fcxlt_authuser b', 'a.auth_id=b.id', 'LEFT')
            ->field('a.auth_id as id')
            ->find();

        // 如果查到了上级信息且上级不是根节点(这里假设1为根)
        if (!empty($infos) && $infos['id'] > 1) {
            $res .= $infos['id'] . ",";
            // 关键:必须return递归调用的结果
            return $this->getWinfo($infos['id'], $res);
        } else {
            // 到达根节点或结束,返回累积的字符串
            return $res;
        }
    } else {
        return $res;
    }
}

第2步:控制器中调用并解析结果

在控制器中传入目标ID,函数返回以逗号分隔的上级ID字符串。最后通过截取和分割,得到纯数字数组供后续使用。

// 初始调用,可将当前ID也加入字符串以便处理边界
$ids = $this->getWinfo($targetId, $targetId . ',');
// 去掉末尾多余的逗号
$id_in = substr($ids, 0, strlen($ids) - 1);
// 转换为整数数组
$id_arr = explode(',', $id_in);

场景二:递归实现无限极分类树

另一种常见需求是将数据库中的平铺数据(包含ID和PID)转换为嵌套的树形数组,便于前端渲染分类菜单。这需要从内存数据中进行递归匹配。

准备条件:数据模型假设

数据源为包含 id, pid, name 字段的数组或从数据库查出的列表。例如:

ID PID 名称
1 0 汽车
2 1 欧拉
3 1 吉利
4 3 沃尔沃
5 1 大众

第1步:构建递归树生成函数

利用静态变量 $list 避免每次递归重新声明导致的覆盖问题。核心逻辑是:遍历未处理的节点,找到 pid 等于当前查找ID的节点,将其加入结果集,然后以其ID为新父ID继续递归。

/**
 * 递归实现无限极分类
 * @param array $array 所有分类数据
 * @param int $pid 父ID
 * @param int $level 层级深度,用于格式化显示
 * @return array $list 构建树形后的数组
 */
function getTree($array, $pid = 0, $level = 0) {
    // 声明静态数组,防止多次递归调用时重置
    static $list = [];

    foreach ($array as $key => $value) {
        // 如果当前节点的父ID等于我们要找的父ID
        if ($value['pid'] == $pid) {
            // 添加层级属性,方便后续缩进显示
            $value['level'] = $level;
            $list[] = $value;
            // 将该节点从数组中移除,减少后续无用的遍历消耗
            unset($array[$key]);
            // 递归查找该节点的子节点,层级+1
            getTree($array, $value['id'], $level + 1);
        }
    }
    return $list;
}

第2步:调用并输出结果

执行函数后,将得到的树形数组进行遍历。可利用 level 属性控制缩进,直观展示层级关系。

// 假设 $sourceData 是从数据库取出的所有分类数据
$resultTree = getTree($sourceData);

foreach ($resultTree as $item) {
    // str_repeat 生成缩进符,level=0无缩进,level=1一个'--',以此类推
    echo str_repeat('--', $item['level']) . $item['name'] . '
'; }

输出效果如下:

河北省
--邯郸市
----永年区
--武安市
北京市
--朝阳区
----望京
----酒仙桥
--通州区

辅助技巧:Null值转空字符串

在处理上述数据结构时,若数据库中某些字段可能为 NULL,为避免JSON序列化或界面展示出错,可使用工具函数将数组中的 NULL 统一转换为空字符串。

public function convertNullToEmptyString($data) {
    return collect($data)->map(function ($value) {
        if (is_null($value)) {
            return '';
        }
        return is_array($value) ? $this->convertNullToEmptyString($value) : $value;
    })->toArray();
}

// 测试用例
$data = [
    ['name' => 'shawn', 'email' => 'test@test.com'],
    ['name' => null, 'company' => 'Test Co']
];
var_dump($this->convertNullToEmptyString($data));

以上就是PHP递归实现无限上级ID回溯与树形分类的详细内容,更多关于PHP层级数据处理与递归算法的资料请关注本站其它相关文章!

相关标签:

免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。

Python 相关产品和应用

全部下载
Selenium

Selenium

4.51.0 · Windows

用于浏览器自动化和 Web 测试的 Python 工具。

scikit-learn

scikit-learn

1.9.1 · Windows

常用 Python 机器学习算法与模型评估工具库。

Black

Black

26.10.1 · Windows

强调一致性的 Python 自动代码格式化工具。

Ruff

Ruff

0.17.1 · macOS

由 Rust 编写的高速 Python 代码检查和格式化工具。

pytest

pytest

9.1.1 · Windows

简洁而强大的 Python 自动化测试框架。

FastAPI

FastAPI

0.146.0 · Windows

高性能 Python API 框架,支持类型提示和自动接口文档。

Flask

Flask

3.1.3 · Windows

轻量灵活的 Python Web 应用框架。

Django

Django

6.1.2 · Windows

成熟的 Python Web 框架,适合构建内容站点和业务系统。

Spyder

Spyder

6.1.7 · Windows

面向科学计算与数据分析的 Python 集成开发环境。

SciPy

SciPy

1.18.1 · Windows

面向科学、工程和技术计算的 Python 算法库。