如何基于5张指定数据表获取分类、子分类及文章并输出嵌套ul HTML
解决方案
一、SQL查询调整
你原来的SQL仅获取了父ID为99的一级分类,没有覆盖一级分类下的多层子分类,我们用递归CTE(支持MySQL 8.0+、MariaDB 10.2+及以上版本)拉取完整的分类树,调整后语句如下:
WITH RECURSIVE category_tree AS ( -- 先获取根节点下的一级分类 SELECT ac.articlecat_id, ac.parent_id, acd.articlecat_name FROM table_article_categories AS ac INNER JOIN table_article_categories_description AS acd ON ac.articlecat_id = acd.articlecat_id AND acd.language_id = 1 WHERE ac.parent_id = 99 AND ac.articlecat_status = 1 AND ac.articlecat_id != 77 UNION ALL -- 递归获取所有子分类 SELECT ac_child.articlecat_id, ac_child.parent_id, acd_child.articlecat_name FROM table_article_categories AS ac_child INNER JOIN category_tree AS ct ON ac_child.parent_id = ct.articlecat_id INNER JOIN table_article_categories_description AS acd_child ON ac_child.articlecat_id = acd_child.articlecat_id AND acd_child.language_id = 1 WHERE ac_child.articlecat_status = 1 AND ac_child.articlecat_id != 77 ) -- 关联获取分类下的文章 SELECT ct.parent_id, ct.articlecat_id, ct.articlecat_name, a.articles_id, ad.articles_heading_title AS article_name FROM category_tree AS ct LEFT JOIN table_article_to_article_categories AS atac ON atac.articlecat_id = ct.articlecat_id LEFT JOIN table_articles AS a ON a.articles_id = atac.articles_id AND a.articles_status = 1 LEFT JOIN table_articles_description AS ad ON ad.articles_id = a.articles_id AND ad.language_id = 1 ORDER BY ct.articlecat_name ASC, article_name ASC
如果用的是不支持递归CTE的低版本数据库,可以先查询所有符合状态的分类,在代码层面组装分类树,不需要在SQL层做递归处理。
二、后续数据处理&HTML生成逻辑
核心思路是先把SQL返回的扁平数据转换成嵌套的树形结构,再递归生成嵌套<ul>标签,通用处理步骤如下:
- 结构化数据
遍历SQL查询结果,把数据整理成两层映射:
- 分类映射:键为分类ID,值为分类详情(名称、父ID、子分类列表、文章列表)
- 父分类映射:键为父分类ID,值为该父分类下的所有子分类ID列表
遍历过程中遇到文章ID非空的条目,就把文章标题加入对应分类的文章列表里,注意分类信息要去重,不要重复存储同一分类的信息。
- 递归生成HTML
写一个递归函数,输入为父分类ID,输出为该分类下的嵌套<ul>字符串,此处以PHP为例,其他语言逻辑一致:
function build_category_ul($parent_id, $category_map, $parent_child_map) { $html = '<ul>'; // 遍历当前父分类下的所有子分类 foreach ($parent_child_map[$parent_id] ?? [] as $cat_id) { $cat = $category_map[$cat_id]; $html .= '<li>' . htmlspecialchars($cat['articlecat_name']); // 先添加子分类的嵌套列表 if (isset($parent_child_map[$cat_id])) { $html .= build_category_ul($cat_id, $category_map, $parent_child_map); } // 再添加当前分类下的文章列表 if (!empty($cat['articles'])) { $html .= '<ul>'; foreach ($cat['articles'] as $article) { $html .= '<li>' . htmlspecialchars($article) . '</li>'; } $html .= '</ul>'; } $html .= '</li>'; } $html .= '</ul>'; return $html; } // 调用方法,根分类的父ID是99 echo build_category_ul(99, $category_map, $parent_child_map);
内容的提问来源于stack exchange,提问作者user3740970
相关产品推荐
相关产品推荐

