
本文介绍如何使用递归函数在 php 中实现无限层级的分类列表渲染,解决传统嵌套循环无法处理深层子类的问题,并提供安全的预处理语句写法与缩进控制方案。
本文介绍如何使用递归函数在 php 中实现无限层级的分类列表渲染,解决传统嵌套循环无法处理深层子类的问题,并提供安全的预处理语句写法与缩进控制方案。
在构建内容管理系统(CMS)、电商网站或知识库时,分类结构往往不是扁平的两层关系,而是存在三级、四级甚至更深的嵌套。若沿用多个 while 循环手动逐层查询(如先查一级、再查二级、再查三级),不仅代码冗余、难以维护,更无法应对动态深度变化。递归调用是解决此类树形结构遍历问题的标准且优雅的方式。
以下是一个完整、安全、可扩展的实现方案:
<?php function outputCategory($conn, $parent_id = 0, $indent = 0) {
// 使用预处理语句防止 SQL 注入,绑定整型参数
$sql = "SELECT `cat_id`, `cat_name` FROM `categories`
WHERE `cat_parent_id` = ?
ORDER BY `cat_name` ASC";
$stmt = mysqli_stmt_init($conn);
if (!mysqli_stmt_prepare($stmt, $sql)) {
error_log("Failed to prepare statement: " . mysqli_error($conn));
return;
}
mysqli_stmt_bind_param($stmt, "i", $parent_id);
mysqli_stmt_execute($stmt);
$result = mysqli_stmt_get_result($stmt);
// 遍历当前层级所有子分类
while ($row = mysqli_fetch_assoc($result)) {
$cat_id = (int)$row['cat_id'];
$cat_name = htmlspecialchars($row['cat_name'], ENT_QUOTES, 'UTF-8');
// 根据缩进层级生成对应 CSS 缩进(每层 +20px)
echo "<h3 style=\"text-indent: {$indent}px;\">{$cat_name}";
// 关键:递归调用自身,以当前分类 ID 作为新 parent_id,缩进增加
outputCategory($conn, $cat_id, $indent + 20);
}
mysqli_stmt_close($stmt);
}
// 启动递归:从顶级分类(cat_parent_id = 0)开始
outputCategory($conn);
?>
✅ 关键设计说明:
-
参数化连接对象:避免
global $conn,显式传参更利于测试与解耦; -
SQL 安全加固:全程使用
mysqli_stmt_*预处理 + 参数绑定,杜绝注入风险; -
输出转义:
htmlspecialchars()防止 XSS,尤其当分类名含 HTML 字符时; -
缩进可控:
$indent参数随递归深度线性增长,视觉上清晰体现层级关系; -
无深度限制:只要数据库支持(如合理设置
max_execution_time和memory_limit),可自动处理任意深度;
⚠️ 注意事项:
- 确保数据库中
cat_parent_id字段对顶级分类统一设为0(而非NULL),否则需调整 WHERE 条件(如IS NULL或COALESCE(cat_parent_id, 0) = ?); - 若分类数量极大(如 >5000 条),建议结合缓存(如 Redis 存储渲染后的 HTML 片段)或改用闭包表(Closure Table)优化查询性能;
- 生产环境应添加错误日志记录,而非静默失败(示例中已包含
error_log);
该方案将原本需要 N 层嵌套的手动循环,简化为一次函数调用,逻辑清晰、扩展性强,是 PHP 处理树形数据的经典实践。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











