扁平结构:
$items = array(
5 => array('id' => 5, 'pid' => 2, 'name' => '鸡西市'),
4 => array('id' => 4, 'pid' => 2, 'name' => '哈尔滨市'),
1 => array('id' => 1, 'pid' => 0, 'name' => '江西省'),
2 => array('id' => 2, 'pid' => 0, 'name' => '黑龙江省'),
7 => array('id' => 7, 'pid' => 4, 'name' => '南岗区'),
6 => array('id' => 6, 'pid' => 4, 'name' => '香坊区'),
3 => array('id' => 3, 'pid' => 1, 'name' => '南昌市'),
90 => array('id' => 100, 'pid' => 3, 'name' => '南昌市-县'),
);
通过引用的方式形成无限极分类树
/**
* 通过引用的方式 生成无限级分类
* 弊端,不能进行 分类结构的的格式化。
* @param array $source
* @param string $primaryKey
* @param string $parentKey
* @param string $childrenKey
* @return array
*/
public function listToTreeByReference(array $source,$primaryKey = 'id', $parentKey = 'pid',$childrenKey = 'children')
{
$tree = [];
$newData = array_column($source,NULL,$primaryKey);
foreach ($newData as $key => &$value) {
if ($value[$parentKey] > 0) {
//不是根节点的将自己的地址放到父级的child节点
$newData[$value[$parentKey]][$childrenKey][] = &$value;
} else {
//根节点直接把地址放到新数组中
$tree[] = &$newData[$value[$primaryKey]];
}
}
return $tree;
}
如果需要格式化无限极分类树:
结构中增加了 level【当前层级】,path【当前节点路径】和isLeaf【当前节点是否是叶子结点】 字段。
/**
* @param $data
* @param int $id
* @param int $level
* @param array $path
* @param string $pid
* @param string $children
* @return array
*/
function listToTreeByRecursion($data, $id = 0,$level = 1,$path = [],$pid = 'pid',$children = 'children'){
//初始化儿子
//初始化儿子
$child = [];
//循环所有数据找$id的儿子
foreach ($data as $key => $datum) {
$datum['isLeaf'] = false;
//找到儿子了
if ($datum[$pid] == $id) {
//路径
$datum['path'] = array_merge($path,array($id));
//当前层级
$datum['level'] = $level;
//保存下来,然后继续找儿子的儿子
$child[$datum['id']] = $datum;
//先去掉自己,自己不可能是自己的儿孙
unset($data[$key]);
//递归找,并把找到的儿子放到一个child的字段中
$child[$datum['id']][$children] = $this->listToTreeByRecursion($data, $datum['id'],$level + 1,$datum['path']);
//归来,判断是否是叶子节点
if(empty($child[$datum['id']][$children])){
$child[$datum['id']]['isLeaf'] = true;
}
}
}
return array_values($child);
}
树形结构示例:
[
{
"id": 1,
"pid": 0,
"name": "江西省",
"isLeaf": false,
"path": [
0
],
"level": 1,
"children": [
{
"id": 3,
"pid": 1,
"name": "南昌市",
"isLeaf": false,
"path": [
0,
1
],
"level": 2,
"children": [
{
"id": 100,
"pid": 3,
"name": "南昌市-县",
"isLeaf": true,
"path": [
0,
1,
3
],
"level": 3,
"children": []
}
]
}
]
},
{
"id": 2,
"pid": 0,
"name": "黑龙江省",
"isLeaf": false,
"path": [
0
],
"level": 1,
"children": [
{
"id": 5,
"pid": 2,
"name": "鸡西市",
"isLeaf": true,
"path": [
0,
2
],
"level": 2,
"children": []
},
{
"id": 4,
"pid": 2,
"name": "哈尔滨市",
"isLeaf": false,
"path": [
0,
2
],
"level": 2,
"children": [
{
"id": 7,
"pid": 4,
"name": "南岗区",
"isLeaf": true,
"path": [
0,
2,
4
],
"level": 3,
"children": []
},
{
"id": 6,
"pid": 4,
"name": "香坊区",
"isLeaf": true,
"path": [
0,
2,
4
],
"level": 3,
"children": []
}
]
}
]
}
]
树形结构->扁平结构
* @param array $tree 原来的树
* @param string $children 孩子节点的键
* @param array $list 过渡用的中间数组,
* @return array
*/
function treeToList($tree, &$list = array(),$children = 'children')
{
if(is_array($tree)) {
foreach ($tree as $value) {
$refer = $value;
if(!empty($refer[$children])){
unset($refer[$children]);
$this->treeToList($value[$children],$list);
}
$list[] = $refer;
}
}
return $list;
}