如何在Yii2中展示带有子分类的分类结构?
分类树形嵌套列表的最佳实现方案
这是开发中很常见的分类树形渲染需求,咱们可以通过「构建树形数据结构 + 递归生成HTML」的组合方式来实现,既高效又易维护。
步骤1:将扁平数组转换为嵌套树形结构
首先需要把从数据库拿到的扁平分类数组,转换成父子层级分明的树形结构。这个步骤的时间复杂度是O(n),效率很高:
function buildTree(array $categories) { // 先把所有分类用id做索引,方便快速查找父分类 $indexed = []; foreach ($categories as $cat) { // 注意你的数组里parent_id字段多了个空格,这里先修正(也可以在查询时避免这个问题) $cat['parent_id'] = trim($cat['parent_id ']); $cat['children'] = []; $indexed[$cat['id']] = $cat; } // 遍历每个分类,把它放到父分类的children数组里 $tree = []; foreach ($indexed as $id => $cat) { if ($cat['parent_id'] == 0) { // 顶级分类直接加入树形结构 $tree[] = $cat; } else { // 子分类加入对应父分类的children if (isset($indexed[$cat['parent_id']])) { $indexed[$cat['parent_id']]['children'][] = $cat; } } } return $tree; } // 调用函数构建树形结构 $flatCategories = Category::find()->asArray()->all(); $categoryTree = buildTree($flatCategories);
步骤2:递归渲染HTML嵌套列表
有了树形结构后,就可以用递归函数来生成对应的HTML列表了,逻辑非常清晰:
function renderTree(array $tree) { if (empty($tree)) { return ''; } $html = '<ul>'; foreach ($tree as $node) { // 用htmlspecialchars处理标题,避免XSS风险 $html .= '<li>' . htmlspecialchars($node['title']); // 如果有子分类,递归渲染子列表 if (!empty($node['children'])) { $html .= renderTree($node['children']); } $html .= '</li>'; } $html .= '</ul>'; return $html; } // 生成最终的HTML $categoryHtml = renderTree($categoryTree); echo $categoryHtml;
为什么这是最佳方式?
- 高效:树形结构构建只需要遍历两次数组,*O(n)*的时间复杂度,处理大量分类数据也不会有性能问题
- 可复用:
buildTree和renderTree都是通用函数,后续其他树形结构的需求也能直接复用 - 易维护:逻辑拆分清晰,树形结构和渲染逻辑分离,后续修改样式或者调整层级规则都很方便
小提醒:你的原始数组里
parent_id字段后面多了个空格(parent_id),记得在查询或者处理时修正,否则会导致父分类匹配失败哦!
内容的提问来源于stack exchange,提问作者Masoud92m
相关产品推荐
相关产品推荐

