• 0
  • 0

PHP 无限极分类数组转换为列表结构和树结构

2019-11-26 763 0 admin 所属分类:PHP 记录

现有如下表结构可以构造多级分类

CREATE TABLE `navs` (
`id`  int(11) UNSIGNED NOT NULL AUTO_INCREMENT ,
`name`  varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '名称' ,
`created_at`  int(11) UNSIGNED NULL DEFAULT NULL ,
`pid`  int(11) UNSIGNED NULL DEFAULT 0 COMMENT '父ID支持二级分类' ,
`deep`  tinyint(3) UNSIGNED NOT NULL DEFAULT 0 COMMENT '区域深度' 
PRIMARY KEY (`id`)
)
ENGINE=InnoDB
DEFAULT CHARACTER SET=utf8 COLLATE=utf8_general_ci
COMMENT='分类表'
;

需要在列表中获取所有记录按照层级依附的顺序排列。考虑到分类元素记录个数有限,可以全部遍历出来,这个时候需要适当格式化。

//获取全部记录
function all() {
    $sql = '';
    if ($_GET['pid']) {
        $sql.=' WHERE pid='.intval($_GET['pid']);
    }
    $rows = DB::fetch_all("SELECT * FROM " . DB::table('navs').$sql);
    return $rows;
}

//格式化记录
function allSelect($pid=0) {
    $rows = all();
    $rows = formatTreeToArray($rows,$pid);
    return $rows;
}

通过先将集合转换为树结构,然后将树结构转换为列表 可以得到有序相邻的集合

//格式化树结构成列表信息
function formatTreeToArray($data,$pid=0) {
    if ($pid>0) {
        $row = C::t('navs')->fetch($pid);
        if (!$row){
            return [];
        } 
        //取相对深度
        $deep = $row['deep'] - $data[0]['deep'];
    } else {
        //从根节点开始算深度
        $deep = $data[0]['deep'];
    }
    
    $list = [];
    foreach ($data as $k => &$v) {
        $pre_str = '';
        if ($v['deep']>=2) {
            for ($i=0; $i < $v['deep']-1; $i++) { 
                $pre_str.="——";
            }
            $pre_str.="|";
        } 
        
        $v['format_name'] = $pre_str.$v['name'];
        $list[$v['id']] = $v;
        unset($v);
    }
    //转换成树结构
    $list = generateTree($list);

    //找到特定的那一分支
    if ($pid>0) {
        $target_data = [];
        findTargetTree($list,$pid,$target_data);
        $list = [$target_data];
    }

    //递归元素 转换成数组并列
    $data = [];
    treeToArr($list,$data);
    return $data;
}

//将数据库记录集返回的数组转换成树结构
function generateTree($items){
    $tree = array();
    foreach($items as $item){
        if(isset($items[$item['pid']])){
            $items[$item['pid']]['son'][] = &$items[$item['id']];
        }else{
            $tree[] = &$items[$item['id']];
        }
    }
    return $tree;
}


//递归将树转换为列表 保证能够使得子元素能够与上层元素相邻 
function treeToArr($items,&$data) {
    foreach ($items as $k => $v) {
        $son = $v['son'];
        unset($v['son']);   
        $data[] = $v;
        if ($son) {
            treeToArr($son,$data);
        }
    }
}

//找到指定父节点的旁支
function findTargetTree($data,$pid,&$targetdata) {
    foreach ($data as $k => $v) {
        if ($v['id']==$pid) {
            $targetdata = $v;
        } else {
            findTargetTree($v['son'],$pid,$targetdata);
        }
    }
}


返回顶部