无限级分类的简单实现

引子
作为菜鸟的我面试过程中总是会被虐的体无完肤,即使知道是怎么一回事,但由于没有彻底掌握住,还是在关键时刻无法及时运用。所以多总结应该是我现在时常要做的事。
遇到的这个机试题就是关于无限级分类的知识。无限级分类在项目中运用是比较平常的,逻辑也不会太难理解:一个父级下面包含多个子级。
题目是这样的:点击下拉框选择,输入名称,添加,到对应的层级中。然后还要可以删除。
实现大概效果图如下:

无限级分类的简单实现
文章图片
图1
无限级分类的简单实现
文章图片
图2 实现
1、数据库 无限级分类的简单实现
文章图片
数据库

添加的逻辑:当某行数据的pid等于另一行数据中的id时,如id为54的广州市,其pid=53,即对应的是广东省,所以广州市是在广东省下面的。以此类推。
【无限级分类的简单实现】删除的逻辑:删除某个父类,其下所有子类都需删除。
2、代码 为了效果稍微好点,采取了jq\ajax,并用了mvc框架。
Controller:
public function index() { $data = https://www.it610.com/article/DB::name('user')->order('id asc')->select(); //调用树 $li = new PersonModel; $tree = $li->getTree($data); $html = $li->html($tree); $this->assign('tree',$tree); $this->assign('data',$data); $this->assign('html',$html); return $this->fetch(); }public function add() { $data = https://www.it610.com/article/$_POST; $pid = $_POST['pid']; if($data) { if($pid == 0) { $result = DB::name('user')->insert(['name'=>$data['name'],'pid'=>0]); //根目录 } else { $insert = DB::name('user')->insert(['name'=>$data['name'],'pid'=>$pid]); //子目录 }$status = 1; $message = '成功'; return ['status' => $status, 'message' => $message]; } else { $status = 0; $message = '失败'; return ['status' => $status, 'message' => $message]; } } public function del() { $data = https://www.it610.com/article/$_POST; $id = $_POST['id']; //获取子集ID $getIds = new PersonModel; $son_ids = $getIds->sonIds($id); $id .= $son_ids; //将删除的父级加上 $ids = explode(',', $id); if($ids) { foreach ($ids as $key => $value) { DB::name('user')->where("id='$value'")->delete(); } $status = 1; $message = '成功'; return ['status'=> $status, 'message' => $message]; } else { $status = 0; $message = '失败'; return ['status'=> $status,'message'=>$message]; } }

Model:
//无极限分类---引用传参 public function li($array) { $items = array(); foreach ($array as $key => $value) { $items[$value['id']] = $value; } $tree = array(); foreach ($items as $key => $value) { if(isset($items[$value['pid']])) { $items[$value['pid']]['son'][] = &$items[$key]; } else { $tree[] = &$items[$key]; } } return $tree; }//无极限分类--递归 public function getTree($array, $pid =0, $level = 0){//声明静态数组,避免递归调用时,多次声明导致数组覆盖 static $list = []; foreach ($array as $key => $value){ //第一次遍历,找到父节点为根节点的节点 也就是pid=0的节点 if ($value['pid'] == $pid){ //父节点为根节点的节点,级别为0,也就是第一级 $value['level'] = $level; //把数组放到list中 $list[] = $value; //把这个节点从数组中移除,减少后续递归消耗 unset($array[$key]); //开始递归,查找父ID为该节点ID的节点,级别则为原级别+1 $this->getTree($array, $value['id'], $level+1); } } return $list; } //输出效果 public function html($tree) { foreach ($tree as $key => $value) { echo str_repeat('|----', $value['level']), $value['name'].'
'; } }//获取删除中的子id集 public function sonIds($id) { $ids = ''; $data = https://www.it610.com/article/DB::name('user')->where("pid='$id'")->select(); if($data) { foreach ($data as $key => $value) { $ids .= ','.$value['id']; $ids .= $this->sonIds($value['id']); } } return $ids; }

其中有两种方法实现:递归和引用
前端:
无限级分类 - 锐客网{$html}
选择: {foreach $data as $val} {/foreach}添加分类:
选择:{foreach $data as $va} {/foreach}

3、代码分析
添加功能: 添加的两种方法:递归和引用,其原理都一样,建立一个空数组,然后就是父亲找儿子的过程,将对应的儿子放在父亲下面。再将其放入空数组中,形成树结构。添加的功能其实就是一个ajax的实现,主要是显示到html中的查询代码处理。逻辑顺序是:选择对应的父类,获取其id,name添加到数据库,model里的方法处理要显示出来的内容。最后返回给页面。
& 引用,将指针指向原数据,后面再循环的时候添加改变数据则是在原数据上改变,所以,可改变原数组。
.= 点等于的意思是拼接等号左右两边的值,如 b = 2,则 b 为1,2
删除功能 通过点击选择父类id,查找出其下所有子id。方法就是通过上面说的点等于符号,在遍历中将其所有的id封装成一个字符串返回。再拼接上父级id,最后使用explode函数将字符串变成数组。
总结
php中无限级分类实现的常用两种方法——递归与引用。

    推荐阅读