php 无限级分类就像是一棵树,这棵树有自己的根部,然后主干,枝干在到叶子,越是向前越茂密 家谱树是无限极分类的表现形式之一,另一个是子孙树。 从某个节点开始向上寻找其父节点,再找父节点的父节点,直到找不到为止
。按照这种寻找,形成的一个类似树状的结构,就叫做家谱树。 而子孙树与其相反,子孙树类似于生物书中的遗传图,从某个节点开始寻找它的子节点,再找子节点的子节点,直到寻找完毕。这样形成的树状结构就叫做子孙树。
子孙树
$categories = array(
array('id'=>1,'name'=>'电脑','pid'=>0),
array('id'=>2,'name'=>'手机','pid'=>0),
array('id'=>3,'name'=>'笔记本','pid'=>1),
array('id'=>4,'name'=>'台式机','pid'=>1),
array('id'=>5,'name'=>'智能机','pid'=>2),
array('id'=>6,'name'=>'功能机','pid'=>2),
array('id'=>7,'name'=>'超级本','pid'=>3),
array('id'=>8,'name'=>'游戏本','pid'=>3),
);
$tree = array();
//将分类id作为数组key,并创建son单元
foreach($categories as $category){
$tree[$category['id']] = $category;
$tree[$category['id']]['son'] = array();
}
//利用引用,将每个分类添加到父类son数组中,这样一次遍历即可形成树形结构。
foreach ($tree as $k=>$item) {
if ($item['pid'] != 0) {
$tree[$item['pid']]['son'][] = &$tree[$k];
}
}
print_r($tree);
Array
(
[1] => Array
(
[id] => 1
[name] => 电脑
[pid] => 0
[son] => Array
(
[0] => Array
(
[id] => 3
[name] => 笔记本
[pid] => 1
[son] => Array
(
[0] => Array
(
[id] => 7
[name] => 超级本
[pid] => 3
[son] => Array
(
)
)
[1] => Array
(
[id] => 8
[name] => 游戏本
[pid] => 3
[son] => Array
(
)
)
)
)
[1] => Array
(
[id] => 4
[name] => 台式机
[pid] => 1
[son] => Array
(
)
)
)
)
[2] => Array
(
[id] => 2
[name] => 手机
[pid] => 0
[son] => Array
(
[0] => Array
(
[id] => 5
[name] => 智能机
[pid] => 2
[son] => Array
(
)
)
[1] => Array
(
[id] => 6
[name] => 功能机
[pid] => 2
[son] => Array
(
)
)
)
)
[3] => Array
(
[id] => 3
[name] => 笔记本
[pid] => 1
[son] => Array
(
[0] => Array
(
[id] => 7
[name] => 超级本
[pid] => 3
[son] => Array
(
)
)
[1] => Array
(
[id] => 8
[name] => 游戏本
[pid] => 3
[son] => Array
(
)
)
)
)
[4] => Array
(
[id] => 4
[name] => 台式机
[pid] => 1
[son] => Array
(
)
)
[5] => Array
(
[id] => 5
[name] => 智能机
[pid] => 2
[son] => Array
(
)
)
[6] => Array
(
[id] => 6
[name] => 功能机
[pid] => 2
[son] => Array
(
)
)
[7] => Array
(
[id] => 7
[name] => 超级本
[pid] => 3
[son] => Array
(
)
)
[8] => Array
(
[id] => 8
[name] => 游戏本
[pid] => 3
[son] => Array
(
)
)
)
// 递归函数的三种实现方式:引用做参数 全局变量 静态变量
function tree($items){
$tree=array();
$packData=array();
foreach ($items as $data) {
$packData[$data['id']] = $data;
}
foreach ($packData as $key =>$val){
if($val['pid']==0){//代表跟节点
$tree[]=& $packData[$key];
}else{
//找到其父类
$packData[$val['pid']]['son'][]=& $packData[$key];
}
}
return $tree;
}
function getTree($data, $pId)
{
$tree = [];
foreach($data as $k => $v)
{
if($v['pid'] == $pId){
//父亲找到儿子
$v['son'] = getTree($data, $v['id']);
$tree[] = $v;
//unset($data[$k]);
}
}
return $tree;
}
$tree = getTree($categories, 0);
print_r($tree);
Array
(
[0] => Array
(
[id] => 1
[name] => 电脑
[son] => Array
(
[0] => Array
(
[id] => 3
[name] => 笔记本
[son] => Array
(
[0] => Array
(
[id] => 7
[name] => 超级本
[son] => Array
(
)
)
[1] => Array
(
[id] => 8
[name] => 游戏本
[son] => Array
(
)
)
)
)
[1] => Array
(
[id] => 4
[name] => 台式机
[son] => Array
(
)
)
)
)
[1] => Array
(
[id] => 2
[name] => 手机
[son] => Array
(
[0] => Array
(
[id] => 5
[name] => 智能机
[son] => Array
(
)
)
[1] => Array
(
[id] => 6
[name] => 功能机
[son] => Array
(
)
)
)
)
)
function genTree2($items) {
foreach ($items as $item)
$items[$item['pid']]['son'][$item['id']] = &$items[$item['id']];
return isset($items[0]['son']) ? $items[0]['son'] : array();
}
function genTree3($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 subtree($arr,$id=0,$lev=1) {
$subs = array(); // 子孙数组
foreach($arr as $v) {
if($v['pid'] == $id) {
$v['lev'] = $lev;
$subs[] = $v;
$subs = array_merge($subs,subtree($arr,$v['id'],$lev+1));
}
}
return $subs;
}
print_r(subtree($categories,1));
Array
(
[0] => Array
(
[id] => 3
[name] => 笔记本
[pid] => 1
[lev] => 1
)
[1] => Array
(
[id] => 7
[name] => 超级本
[pid] => 3
[lev] => 2
)
[2] => Array
(
[id] => 8
[name] => 游戏本
[pid] => 3
[lev] => 2
)
[3] => Array
(
[id] => 4
[name] => 台式机
[pid] => 1
[lev] => 1
)
)
function familytree($arr,$id) {
$tree = array();
while($id !== 0) {
foreach($arr as $v) {
if($v['id'] == $id) {
$tree[] = $v;
$id = $v['pid'];
break;
}
}
}
return $tree;
}
function familytree2($arr,$id) {
$tree = array();
foreach($arr as $v) {
if($v['id'] == $id) {// 判断要不要找父栏目
if($v['pid'] > 0) { // 说明有父栏目
$tree = array_merge($tree,familytree($arr,$v['pid']));
}
$tree[] = $v;
}
}
return $tree;
}
print_r(familytree($categories,4));
Array
(
[0] => Array
(
[id] => 1
[name] => 电脑
[pid] => 0
)
[1] => Array
(
[id] => 4
[name] => 台式机
[pid] => 1
)
)
function tree($list, $parent_id, $level=0) {
//应该是静态的局部变量,这样才能保证,在递归调用时,所有
//的tree方法,操作的是一个Tree空间。
static $tree = array();//保存找到的分类的数组
//遍历所有分类,通过parent_id判断,哪些是我们正在查找的
foreach($list as $row) {
//判断当前所遍历的分类$row, 是否是当前需要查找的子分类
if($row['pid'] == $parent_id) {
//找到了一个分类
$row['level'] = $level;
$tree[] = $row;
//继续查找当前$row所代表的分类的子分类
tree($list, $row['id'], $level+1);
}
}
return $tree;
}
print_r(tree($categories,'pid'));
Array
(
[0] => Array
(
[id] => 1
[name] => 电脑
[pid] => 0
[level] => 0
)
[1] => Array
(
[id] => 3
[name] => 笔记本
[pid] => 1
[level] => 1
)
[2] => Array
(
[id] => 7
[name] => 超级本
[pid] => 3
[level] => 2
)
[3] => Array
(
[id] => 8
[name] => 游戏本
[pid] => 3
[level] => 2
)
[4] => Array
(
[id] => 4
[name] => 台式机
[pid] => 1
[level] => 1
)
[5] => Array
(
[id] => 2
[name] => 手机
[pid] => 0
[level] => 0
)
[6] => Array
(
[id] => 5
[name] => 智能机
[pid] => 2
[level] => 1
)
[7] => Array
(
[id] => 6
[name] => 功能机
[pid] => 2
[level] => 1
)
)
$ids = array_column($categories,'pid','id');
Array
(
[1] => 0
[2] => 0
[3] => 1
[4] => 1
[5] => 2
[6] => 2
[7] => 3
[8] => 3
)
$id = 7;
while($ids[$id]) {
$id = $ids[$id];
}
echo $id; // 1