🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
``` <?php namespace Org\LAMP; class CatTree { private static $order = 'ord'; //有排序字段和表的对应,如果没有这个字段可以不写 private $id = 'typeid'; //表的id字段 private $pid = 'pid'; //表的父级pid字段 private $typename = 'name'; //表字段对应的类型名 private $son = 'subcat'; //如果有子数组,子数组下标,可以自定义值(在新数组中出现) private $level = 'level'; //默认的新加级别下标, 可以自定义值 private $path = 'path'; //默认的路径下标,可以自定义 private $ps = ','; //默认的路径分隔符号,可以自己字义 private $childs = 'childs'; //默认的子数组下标,可以自己定义 private $narr = array(); //放分完级别后的数组 private $i; //临时的一个记数 private $pathname = 'pathname'; //默认的全路径名,可以自己定义belongs //设置表字段id public function setId($value='') { $this->id=$value; } //表的父级pid字段 public function setPid($value='') { $this->pid=$value; } public function setTypename($value='') { $this->typename=$value; } public function setPathname($value='') { $this->pathname=$value; } /** * * 获取分类数结构 * 第二个参数为true时,补全父类 如:衣服/上衣/ * @param $items array 从数据库查询出来的分类信息(二维数组) * @param $allpath boolean 是否返回全路径类型名称 默认不返回提高效率 * @return 返回多维数组 */ public function getTree($items,$allpath=false){ if(empty($items)) return array(); $tree = array(); //格式化的树 $tmpMap = array(); //临时扁平数据 //如果数组中有排序字段则先排序 返回排序后的数组 if(array_key_exists(self::$order, $items[0])) {//二维数组中存在排序的字段则进行排序 usort($items, array(__CLASS__, "compare"));//用户自定义的函数或者方法排序(当前类的compare方法) } //取出id座位键名将该数据装入$tmpMap(将下标值替换成typeid) foreach ($items as $item) { $tmpMap[$item[$this->id]] = $item; } //自定义开始:取出带父类别名的类别名 if ($allpath) { foreach ($tmpMap as $key =>$temp) { //如果pid>0即存在父类别 if ($temp[$this->pid ]) { //拿到path $path=$temp[$this->path]; $pathArr=explode($this->ps, $path);//fuid数组 //取出父id数组的名字 $aname=''; foreach ($pathArr as $pid) { if ($pid!=0) { foreach ($tmpMap as $value) { if ($pid==$value[$this->id]) { $aname.=$value[$this->typename].'/'; } } }else{ continue; } } $aname= $aname.$temp[$this->typename]; }else{ $aname=$temp[$this->typename]; } $tmpMap[$key][$this->pathname]=$aname; } } //自定义结束 foreach ($items as $item) { if (isset($tmpMap[$item[$this->pid]])) { //循环原数组,原数组中的pid是临时数组的id时,将原数组的这组数据插入到子数组中 $tmpMap[$item[$this->pid]][$this->son][] = &$tmpMap[$item[$this->id]]; } else { //如果pid=0时 $tree[] = &$tmpMap[$item[$this->id]]; } } return $this->pathchild($tree); } /** * 设置类路路径, 和获取全部子类 * return eg ["childs"] => string(4) "2,3," */ private function pathchild($arr, $path='') { $xarr = array(); foreach ($arr as $k=>$v) { $xarr[$k]=$v; $xarr[$k][$this->path] = $path.$this->ps.$v[$this->pid]; $xarr[$k][$this->childs] = ''; if(isset($xarr[$k][$this->son])) { $xarr[$k][$this->son]=$this->pathchild($xarr[$k][$this->son], $xarr[$k][$this->path]); foreach($xarr[$k][$this->son] as $vv) { $xarr[$k][$this->childs] .= $vv[$this->id]; $xarr[$k][$this->childs] .= $this->ps.$vv[$this->childs]; } } } return $xarr; } /** * * 返回带有层数级别的二维数组 * @param array $arr 从表中获取的数组 * @return array 处理过的数组 */ public function getList($arr, $allpath=false) { $data=$this->getTree($arr, $allpath); return $this->clevel($data); } /** * 转多层数组为二维数组, 并加上层数组别 */ private function clevel($arr, $num=0) { $this->i = $num; //遍历多维数组 foreach ($arr as $v) { if (isset($v[$this->son])) { //遍历后存在子数组情况 $v[$this->level] = $this->i++;//depath $subcat = $v[$this->son];//将子数组临时存放 unset($v[$this->son]);//删除子数组 $v[$this->childs] = trim($v[$this->childs], $this->ps);//去除多余的分隔符 $v[$this->path] = trim($v[$this->path], $this->ps);//去除多余的分隔符 $this->narr[$v[$this->id]]=$v; $this->clevel($subcat, $this->i); } else { $v[$this->level] = $this->i; $v[$this->childs] = trim($v[$this->childs], $this->ps); $v[$this->path] = trim($v[$this->path], $this->ps); $this->narr[$v[$this->id]]=$v; } } $this->i--; return $this->narr; } /** * 内部使用方法, 将按二维数组中的指定排序字段排序 */ private static function compare($x,$y){ if($x[self::$order] == $y[self::$order]) { return 0; } elseif($x[self::$order] < $y[self::$order]){ return -1; } else { return 1; } } } ``` ``` $tree=new Org\LAMP\CatTree(); $tree->setId('partsid'); $tree->setPid('parentid'); $tree->setTypename('pname'); $list=$tree->getList($partsList,true); ``` 简易无限分类 ``` class Arr { /** * 分类树,支持无限极分类 */ public static function getTree($data){ $items = []; foreach ($data as $v) { $items [$v['category_id']] = $v; } $tree = []; foreach ($items as $id => $item){ if (isset($items[$item['pid']])){ $items [$item['pid']]['list'][] = &$items[$id]; }else{ $tree[] = &$items[$id]; } } return $tree; } /** * 限制1-3级分类的个数 */ public static function sliceTreeArr($data, $firstCount=5, $secondCount=3, $threeCount=6){ $data=array_slice($data, 0, $firstCount); foreach($data as $k =>$v){ if(!empty($v['list'])){ $data[$k]['lsit']=array_slice($v['list'], 0, $secondCount); foreach($v['list'] as $kk => $vv){ if(!empty($vv['list'])){ $data[$k]['list'][$kk]['list']=array_slice($vv['list'], 0, $threeCount); } } } } return $data; } } ``` ## **函数方式** ``` /** * 无限分类 河北-廊坊-三河-燕郊-...-北京 * @param $cate * @param string $lefthtml * @param int $pid * @param int $lvl * @return array */ function sameLevelTree($cate, $leftHtml = '|— ', $pid = 0, $lvl = 0, $cate_name="name", $pid_field="pid") { $arr = array(); foreach ($cate as $v) { if ($v[$pid_field] == $pid) { $v['lvl'] = $lvl + 1; $v['left_html'] = str_repeat($leftHtml, $lvl); $v['l_cate_name'] = $v['left_html'] . $v[$cate_name]; $arr[] = $v; $arr = array_merge($arr, sameLevelTree($cate, $leftHtml, $v['id'], $lvl + 1, $cate_name, $pid_field)); } } return $arr; } //优化: function sameLevelTree($cate, $leftHtml = '|— ', $pid = 0, $lvl = 0, $cate_name="name", $pid_field="pid") { $arr = array(); foreach ($cate as $v) { if ($v[$pid_field] == $pid) { $v['lvl'] = $lvl + 1; // $v['left_html'] = str_repeat($leftHtml, $lvl); $lvl>0?$v['left_html'] = $leftHtml:$v['left_html'] = ""; $v['l_cate_name'] = str_repeat("&nbsp;&nbsp;&nbsp;&nbsp;", $lvl).$v['left_html'] . $v[$cate_name]; $arr[] = $v; $arr = array_merge($arr, sameLevelTree($cate, $leftHtml, $v['id'], $lvl + 1, $cate_name, $pid_field)); } } return $arr; } ``` `sameLevelTree($city);` ![](https://img.kancloud.cn/d9/88/d98835f7b48931e0473f1f93ddace07c_517x132.png) `sameLevelTree($city, '');` 无限树状分类 ``` /** * 无限分类 * @param $cate * @param string $lefthtml * @param int $pid * @param int $lvl * @return array */ function nestedTree($data){ $items = [];//将数据的索引换成id对应的索引 foreach ($data as $v) { $items [$v['id']] = $v; } $tree = []; foreach ($items as $id => $item){ //存在此次循环数据的pid有对应的id(数据时)时,将此次循环的数据放入对应的id(数据时)的child中 if (isset($items[$item['pid']])){ $items [$item['pid']]['child'][] = &$items[$id]; /* $items 此时的数据结构如下: [ 1 =>[ "id" => 1, "pid" => 0, "name" => "北京", "child" => [ 2 =>[ "id" => 2, "pid" => 3216, "name" => "东城区", ], 3 =>[ "id" => 3, "pid" => 3216, "name" => "西城区" ] ], ], 2 =>[ "id" => 2, "pid" => 3216, "name" => "东城区" ], 3 =>[ "id" => 3, "pid" => 3216, "name" => "西城区" ], ] */ }else{ //提取顶级数据 $tree[] = &$items[$id]; } } return $tree; } ```