PHP递归实现树形三级联动菜单

闻溪
闻溪
发布时间:2026-10-13| 3人浏览过
原创

本文将详细介绍如何通过PHP的递归算法与MySQL数据库相结合,动态构建一个支持多级嵌套的树形菜单。该方法利用父级ID(parent_id)建立层级关系,能够自动适配不同深度的菜单结构,适用于后台管理、分类导航等场景。

实现原理与准备条件

实现树形菜单的核心在于数据的层级化组织。通常数据库中有一张菜单表,包含至少三个关键字段:菜单项的唯一标识(如 id)、显示的文本名称(如 name)以及其父级菜单的ID(如 parent_id)。根菜单项的 parent_id 通常设为0或NULL。

我们需要在PHP中编写一个递归函数,该函数的职责是:

  1. 查询当前层级的所有子节点:根据传入的父级ID查找符合条件的记录集。
  2. 遍历并输出HTML:将每一条记录转换为对应的HTML标签(如列表项 <li> 或表格行 <tr>)。
  3. 递归调用:如果当前节点还有下级子节点,则再次调用自身处理下一层级。

完整代码结构与操作顺序

第1步:配置数据库连接

首先需要连接到数据库并选择目标库。在实际项目中,应妥善保管账号密码,避免硬编码在公开代码中。

<?php
// 设置基本变量用于跟踪层级和全局ID
$GLOBALS["ID"] = 1;
$layer = 1;

// 连接数据库(示例环境)
$Con = mysql_connect("localhost", "root", "123456");
mysql_select_db("menu", $Con);
?
>

注意:上述代码使用了较旧的 mysql_* 扩展,现代开发建议使用 PDO 或 mysqli,但为了保持原理解析清晰,此处沿用原有逻辑进行演示。

第2步:执行首层查询

从数据库中读取一级菜单(即 parent_id=0 的记录),作为树的根部开始渲染。

<?php
$sql = "SELECT * FROM menu WHERE parent_id=0";
$result = mysql_query($sql, $Con);

if (mysql_num_rows($result) > 0) {
    // 调用递归函数开始渲染
    ShowTreeMenu($Con, $result, $layer);
}
?
>

第3步:核心递归函数实现

这是实现树形结构的关键部分。函数接收数据库连接、当前结果集和当前层级数,负责解析当前层级并处理子层级。

<?php
function ShowTreeMenu($Con, $result, $layer) {
    $numrows = mysql_num_rows($result);
    
    echo "<table cellpadding='0' cellspacing='0' border='0'>";
    
    for ($rows = 0; $rows < $numrows; $rows++) {
        // 获取当前菜单项
        $menu = mysql_fetch_array($result);
        
        // 查询当前菜单的子项
        $sub_sql = "SELECT * FROM menu WHERE parent_id = '" . $menu['id'] . "'";
        $result_sub = mysql_query($sub_sql, $Con);
        
        echo "<tr>";
        
        // 判断是否有子菜单以添加交互图标
        if (mysql_num_rows($result_sub) > 0) {
            echo "<td width='20'><img src='tree_expand.gif' border='0' /></td>";
            echo "<td class='Menu' onClick='javascript:ShowMenu(Menu" . $GLOBALS["ID"] . ")'>";
        } else {
            echo "<td width='20'><img src='tree_collapse.gif' border='0' /></td>";
            echo "<td class='Menu'>";
        }
        
        // 输出链接或纯文本
        if ($menu['url'] != "") {
            echo "<a href='$menu[url]'>" . $menu['name'] . "</a>";
        } else {
            echo $menu['name'];
        }
        
        echo "</td></tr>";
        
        // 如果有子菜单,递归显示并包裹在隐藏的 div/tr 中
        if (mysql_num_rows($result_sub) > 0) {
            echo "<tr id='Menu" . $GLOBALS["ID"]++ . "' style='display:none'>";
            echo "<td width='20'></td>";
            echo "<td>";
            
            $layer++;
            // 递归调用自身,传入子结果集
            ShowTreeMenu($Con, $result_sub, $layer);
            $layer--;
            
            echo "</td></tr>";
        }
    }
    
    echo "</table>";
}
?
>

第4步:前端JS联动控制

为了实现点击展开/折叠的效果,需要一段简单的JavaScript代码来控制CSS样式。在HTML头部引入以下脚本:

<script language='javascript'>
function ShowMenu(menuId) {
    if (menuId.style.display == "none") {
        menuId.style.display = "";
    } else {
        menuId.style.display = "none";
    }
}
</script>

关键知识点说明

  • 全局ID计数:$GLOBALS["ID"] 用于为每一个可能存在的子菜单生成唯一的HTML ID,确保JS能准确找到对应的DOM元素进行切换。
  • 层级缩进:$layer 虽然在此简化版中使用表格布局未做深度缩进,但在实际应用中可通过修改HTML结构(如增加 <div> 的内联样式 padding)来实现视觉上的树状缩进。
  • 性能提示:N+1 查询问题 上述递归实现在每一层都会对数据库发起一次查询。当菜单层级极深或数据量极大时,效率较低。生产环境中建议一次性加载所有相关菜单数据到内存数组中,然后通过数组引用构建树形结构,再渲染HTML。

总结

以上就是基于PHP递归与MySQL数据库实现树形级联菜单的详细内容。这种方法灵活且易于理解,适合中小规模的数据结构展示。更多关于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 算法库。