手把手教你用php实现无限极分类功能


php轻松实现无限极分类功能

本文的 todo 都是需要自行修改的

应用场景

如:

  • 面包屑导航
  • 分类(如:商品分类、课程分类、城市)
  • 文件夹

数据表设计

code字段是为了方便筛选

// todo 表名需要更换
CREATE TABLE `表名` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `pid` int(11) unsigned NOT NULL DEFAULT '0',
  `name` varchar(191) COLLATE utf8_unicode_ci NOT NULL COMMENT '名称',
  `code` varchar(100) COLLATE utf8_unicode_ci NOT NULL DEFAULT '' COMMENT 'code码:上级code+本级id+pid',
  `created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  `updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间',
  PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci ROW_FORMAT=DYNAMIC COMMENT='XXX';

数据表数据

在这里插入图片描述

无限极分类的列表处理逻辑

图片来源于网络

因为是demo,所以都整合到一个function了,请自行拆分

public function getList()
{
    // todo 先查询出数据表的所有数据 data
    $data = Model::get();
    // 处理数据
    $source = [];
    foreach ($data as $v) {
        $source[] = [
            'id' => $v->id,
            'pid' => $v->pid,
            'name' => $v->name,
            'code' => $v->code
        ];
    }
    // 生成tree数据
    $pk = 'id'; //主键标记字段
    $pid = 'pid'; //parent标记字段
    $child = 'children';//child标记字段
    $root = 0;
    $list = $source //要转换的二维结果集
    $tree = [];
    if (is_array($list)) {
        //创建基于主键的数组引用
        $refer = array();
        foreach ($list as $key => $data) {
            $refer[$data[$pk]] = &$list[$key];
            //判断是否存在parent
            $parantId = $data[$pid];
            if ($root == $parantId) {
                $tree[] = &$list[$key];
            } else {
                if (isset($refer[$parantId])) {
                    $parent = &$refer[$parantId];
                    $parent[$child][] = &$list[$key];
                }
            }
        }
    }
    return response()->json([
            'code' => '1',
            'msg' => 'success,
            'data' => $tree
        ]);
}

api返回格式

{
    "code": 1,
    "msg": "success",
    "data": [
        {
            "id": 1,
            "pid": 0,
            "name": "北京",
            "code": "10",
            "children": [
                {
                    "id": 2,
                    "pid": 1,
                    "name": "昌平",
                    "code": "1021",
                    "children": [
                        {
                            "id": 3,
                            "pid": 2,
                            "name": "回龙观",
                            "code": "102132",
                            "children": [
                                {
                                    "id": 4,
                                    "pid": 3,
                                    "name": "金域华府",
                                    "code": "10213243"
                                },
                                {
                                    "id": 8,
                                    "pid": 3,
                                    "name": "融泽家园",
                                    "code": "10213283"
                                }
                            ]
                        },
                        {
                            "id": 5,
                            "pid": 2,
                            "name": "龙泽",
                            "code": "102152",
                            "children": [
                                {
                                    "id": 7,
                                    "pid": 5,
                                    "name": "龙华园",
                                    "code": "10215275"
                                },
                                {
                                    "id": 9,
                                    "pid": 5,
                                    "name": "龙泽苑",
                                    "code": "10215295"
                                }
                            ]
                        }
                    ]
                },
                {
                    "id": 6,
                    "pid": 1,
                    "name": "朝阳",
                    "code": "1061"
                }
            ]
        }
    ]
}

拼装无限极分类name

拼装的字符串实例:

  • 北京/昌平/回龙观
  • 北京/昌平
public function getData()
{
    // 以code为key的分类信息
    $codeList = [];
    // 先查询出数据表的所有数据 list
    $list = Model::get();
    foreach ($list as $v) {
      $codeList[$v['code']] = $v;
      }
    // todo $data 其它列表数据
    foreach($data as &$v) {
        // todo child需要自己拼装
        $child = [
            'pid' => 1,
            'name' => '昌平'
        ];
        $v['str'] = $this->getDeptName($list, $child);
    }
}

/**
 * 拼接组织架构字符串
 * @param $data []
 * @param $child []
 * @return mixed
 * User: WXiangQian
 */
public function getDeptName($data, $child)
{
    $pid = $child['pid'];
    if ($child['pid'] == 0) {
        return $child['name'];
    }
    foreach ($data as $k => $v) {
        if ($child['pid'] == $v['id']) {
            // todo 暂时用 / 去拼接的,也可以用 - 自定义
            $child['name'] = $v['name'] . '/' . $child['name'];
            $child['pid'] = $v['pid'];
            unset($data[$k]);
        }
    }
    // 未找到数据,则返回 “-” 数据
    if ($pid == $child['pid']) {
        return '-';
    }
    return $this->getDeptName($data, $child);
}

实现效果图

在这里插入图片描述
在这里插入图片描述

php轻松实现无限极分类功能就简单到这了,期待你的关注👍


 上一篇
Laravel Api 报错429 Too Many Attempts. Laravel Api 报错429 Too Many Attempts.
429 Too Many Attempts.在 Laravel 中该功能通过内置的 throttle 中间件来实现,该中间件接收两个参数,第一个是次数上限,第二个是指定时间段(单位:分钟) 第一个参数 100 代表每分钟限制 100 次请
2020-09-10
下一篇 
jwt-auth根据token反解析出用户信息 jwt-auth根据token反解析出用户信息
token解密使用authenticate方法,注意要先setToken: use Tymon\JWTAuth\JWTAuth; class VerifySign extends JWTAuth { public functio
2020-08-10
  目录