Skip to content

无限级分类设计

stivepeim edited this page Dec 31, 2020 · 1 revision

无限级分类设计

无限级分类是从顶级节点开始,每一个节点可以有多个子节点(宽),以及多层节点(高);


解决方案

  1. 使用递归算法,也是使用频率最多的,大部分开源程序也是这么处理,不过一般都只用到四级分类。这种算法的数据库结构设计最为简单。category表中一个字段id,一个字段fid(父id)。这样可以根据WHERE id = fid来判断上一级内容,运用递归至最顶层。
    分析:通过这种数据库设计出的无限级,可以说读取的时候相当费劲,所以大部分的程序最多3-4级分类,这就足以满足需求,从而一次性读出所有的数据,再对得到数组或者对象进行递归。本身负荷还是没太大问题。但是如果分类到更多级,那是不可取的办法。
    这样看来这种分类有个好处,就是增删改的时候轻松了…然而就二级分类而言,采用这种算法就应该算最优先了。

  2. 相比于递归算法,第二种优势非常大; 经典案例电脑文件夹设计

1. 顶级节点为电脑
2. 2级节点有 A、B、C、D、E、F、G盘等N个盘
3. 每一个盘都会有N多个文件夹,文件夹套文件夹;文件夹会有子节点存在,文件是当前节点的终止

数据库设计

CREATE TABLE `eb_category` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `pid` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '父级ID',
  `path` varchar(255) NOT NULL DEFAULT '/0/' COMMENT '路径',
  `name` varchar(50) NOT NULL COMMENT '分类名称',
  `type` smallint(2) DEFAULT '1' COMMENT '类型,A盘,2 B盘,3 C盘, 4 D盘, 5 E盘',
  `url` varchar(255) DEFAULT '' COMMENT '自定义跳转地址',
  `extra` text COMMENT '扩展字段 Jsos格式',
  `status` tinyint(1) NOT NULL DEFAULT '1' COMMENT '状态, 1正常,0失效',
  `sort` int(5) NOT NULL DEFAULT '99999' COMMENT '排序',
  `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  `update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
  PRIMARY KEY (`id`) USING BTREE,
  KEY `status+pid` (`pid`,`status`),
) ENGINE=InnoDB AUTO_INCREMENT=305 DEFAULT CHARSET=utf8 COMMENT='分类表';
CREATE TABLE `category` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `pid` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '父级ID',
  `path` varchar(255) NOT NULL DEFAULT '/0/' COMMENT '路径',
  `name` varchar(50) NOT NULL COMMENT '分类名称',
  `type` smallint(2) DEFAULT '1' COMMENT '类型,A盘,2 B盘,3 C盘, 4 D盘, 5 E盘',
  `url` varchar(255) DEFAULT '' COMMENT '自定义地址',
  `extra` text COMMENT '扩展字段 Jsos格式',
  `status` tinyint(1) NOT NULL DEFAULT '1' COMMENT '状态,1 正常,0 失效',
  `sort` int(5) NOT NULL DEFAULT '99999' COMMENT '排序',
  `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  `update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
  PRIMARY KEY (`id`) USING BTREE,
) ENGINE=InnoDB AUTO_INCREMENT=305 DEFAULT CHARSET=utf8 COMMENT='分类表';
  • ### 需要思考的问题
1. 为什么需要path字段
2. path字段如何设计
3. 为什么要设计url字段
4. 如何快速正查询,反查询
    4.1. 如何快速定位一个顶级节点下所有的子节点,形成树形结构需要
    4.2. 如何通过一个子节点快速查询出父节点
5. 无限级分类的应用场景
6. 在项目中如何应用

PHP代码如何实现树形结构

<?php
/**@formatCategory 无线级分类处理
 * @param array $data 数据源
 * @param string $fieldName 字段名
 * @return array
 * @author 张先生
 * @date 2020-03-27
 */
if(!function_exists('formatCategory')){
    function formatCategory(array $data , string $idName = "id", string $fieldName = 'pid', $childrenKey = 'child')
    {
        $items = [];
        foreach ($data as $item) {
            $items[$item[$idName]] = $item;
        }
        $result = array();
        foreach($items as $item){
            if(isset($items[$item[$fieldName]])){
                $items[$item[$fieldName]][$childrenKey][] = &$items[$item[$idName]];
            }else{
                $result[] = &$items[$item[$idName]];
            }
        }
        return $result;
    }
}

几个常用的PHP方法

Clone this wiki locally