如何使用PHP+MySQL实现无层级限制的ul li嵌套列表渲染
实现无限层级嵌套列表解决方案
核心思路
- 一次性查询全表所有数据,避免原代码嵌套查询带来的N+1性能损耗
- 将扁平的数据库数据转换为层级树结构,方便递归处理
- 编写递归渲染函数,自动判断节点是否存在子节点,存在就继续嵌套生成
<ul><li>结构
优化后完整代码
<?php // 一次性查询所有账户数据,无需嵌套查询 $all_akun = $db->query("SELECT * FROM tb_akun")->fetch_all(MYSQLI_ASSOC); // 生成以kode_akun为键的映射表,同时初始化children字段存储子节点 $akun_map = []; foreach ($all_akun as $item) { $akun_map[$item['kode_akun']] = $item; $akun_map[$item['kode_akun']]['children'] = []; } // 组装层级树结构 $root_tree = []; foreach ($all_akun as $item) { if ($item['parent_akun'] == 0) { // 根节点直接加入根树 $root_tree[] = &$akun_map[$item['kode_akun']]; } else { // 非根节点挂载到对应父节点的children数组 if (isset($akun_map[$item['parent_akun']])) { $akun_map[$item['parent_akun']]['children'][] = &$akun_map[$item['kode_akun']]; } } } // 递归渲染列表的函数 function render_ul_li($nodes, $code_prefix = '') { if (empty($nodes)) return ''; $html = '<ul>'; foreach ($nodes as $node) { // 兼容原有编号展示逻辑:根节点去掉后缀0,子节点拼接父级编号 $current_code = empty($code_prefix) ? preg_replace('/0+/', '', $node['kode_akun']) : $code_prefix . '-' . $node['kode_akun']; $html .= '<li>' . htmlspecialchars($current_code) . ' - ' . htmlspecialchars($node['nama_akun']); // 存在子节点则递归渲染 if (!empty($node['children'])) { $html .= render_ul_li($node['children'], $current_code); } $html .= '</li>'; } $html .= '</ul>'; return $html; } ?> <!-- 页面输出 --> <div class="ulli-none"> <?= render_ul_li($root_tree) ?> </div>
方案优势
- 无层级限制,只要数据库中父子关联关系正确,即可自动生成对应嵌套层级
- 仅查询1次数据库,数据量较大时性能远高于原嵌套查询方案
- 代码逻辑解耦,后续需要调整列表展示样式时,仅需要修改递归渲染函数即可
注意事项
- 如果你的数据库操作类返回的查询结果不是关联数组格式,需要对应调整
fetch_all的传参 - 代码中加入了
htmlspecialchars做输出转义,避免XSS安全风险,如果确认账户名称无特殊字符可按需删除
内容的提问来源于stack exchange,提问作者d41d8cd98f00b204e9800998ecf842
相关产品推荐
相关产品推荐

