用数组作模拟数据库取出的数据,用递归根据pid为数组分层,并计算出最大层数。
代码:
<?php
echo "<pre>";
$navClass = new Nav();
$navClass->leftMenu();
class Nav{
public $level =0;
private $levelList = [];
private $pid;
private $list = [
['id'=>'1','title'=>'nav1','pid'=>0,'href'=>''],
['id'=>'2','title'=>'nav1','pid'=>0,'href'=>'1'],
['id'=>'3','title'=>'nav11','pid'=>1,'href'=>'11'],
['id'=>'4','title'=>'nav12','pid'=>1,'href'=>'12'],
['id'=>'5','title'=>'nav111','pid'=>3,'href'=>'111'],
];
public function leftMenu(){
$menu=$this->setMenu();
$this->getMaxLevel($menu);
var_dump($menu);
}
private function setMenu($map = null, $menu = null) {
//var_dump($map,$menu);
if (empty($map) || !is_array($map)) {
$map = [
//'type' => 'user',
'pid' => 0,
];
}
$this->pid = $map['pid'];
$list = $this->searchArray($this->list,$map);
$menu = empty($menu) ? [] : $menu;
if ($list&&count($list) > 0) {
//有子菜单
foreach ($list as $key => $value) {
$menu=$this->setMenuItem($menu, $value['pid'], $value);
$map['pid'] = $value['id'];
$count = $this->searchArray($this->list,$map);
$count = $count?count($count):$count;
//$menu=$this->setMenu($map, $menu);
if($count){
$menu=$this->setMenu($map, $menu);
}
}
}
return $menu;
}
private function setMenuItem($menu, $pid, $item,$level=1) {
$has = false;
if (empty($menu)||empty($pid)) {
$menu[] = $item;
return $menu;
}
foreach ($menu as $key => &$value) {
if ($pid == $value['id']) {
if (!isset($value['sub_nav'])) {
$value['sub_nav'] = [];
}
$value['sub_nav'][] = $item;
$has = true;
return $menu;
}
}
if (!$has) {
foreach ($menu as $key => &$value) {
if (isset($value['sub_nav'])) {
$value['sub_nav'] = $this->setMenuItem($value['sub_nav'], $pid, $item);
}
}
return $menu;
}
}
private function searchArray($list,$map){
if(isset($list[0])){
$arrayList = [];
foreach($list as $key=>$val){
$isItem = false;
foreach ($val as $vk => $vv) {
if(in_array($vk, array_keys($map))){
if($vv==$map[$vk]){
$isItem = true;
}else{
$isItem = false;
}
}
}
if($isItem){
$arrayList[] = $val;
}
}
if(!empty($arrayList)){
return $arrayList;
}else{
return false;
}
}
return false;
}
private function getMaxLevel($menu){
$this->getLevelList($menu);
$this->level = max($this->levelList);
var_dump($this->level);
}
private function getLevelList($menu,$level=0){
foreach ($menu as $key => $value) {
$this->level++;
if(isset($value['sub_nav'])){
$this->getLevelList($value['sub_nav']);
}else{
$this->levelList[] = $this->level;
$this->level-=2;
}
}
}
}
结果:
int(3)
array(2) {
[0]=>
array(5) {
["id"]=>
string(1) "1"
["title"]=>
string(4) "nav1"
["pid"]=>
int(0)
["href"]=>
string(0) ""
["sub_nav"]=>
array(2) {
[0]=>
array(5) {
["id"]=>
string(1) "3"
["title"]=>
string(5) "nav11"
["pid"]=>
int(1)
["href"]=>
string(2) "11"
["sub_nav"]=>
array(1) {
[0]=>
array(4) {
["id"]=>
string(1) "5"
["title"]=>
string(6) "nav111"
["pid"]=>
int(3)
["href"]=>
string(3) "111"
}
}
}
[1]=>
array(4) {
["id"]=>
string(1) "4"
["title"]=>
string(5) "nav12"
["pid"]=>
int(1)
["href"]=>
string(2) "12"
}
}
}
[1]=>
array(4) {
["id"]=>
string(1) "2"
["title"]=>
string(4) "nav1"
["pid"]=>
int(0)
["href"]=>
string(1) "1"
}
}
bug 修改:
当第一个节点的pid不为0时 同节点数据不能进入menu数组。
修改如下:
private function setMenu($map = null, $menu = null, $isHeader = true) {
if (empty($map) || !is_array($map)) {
$map = [
'type' => 'user',
'pid' => 0,
];
}
$list = db('menu')->where($map)->order('sort asc')->select();
$menu = empty($menu) ? [] : $menu;
if ($list && count($list) > 0) {
//有子菜单
foreach ($list as $key => $value) {
if ($isHeader) {
$menu[] = $value;
} else {
$menu = $this->setMenuItem($menu, $value['pid'], $value);
}
$map['pid'] = $value['id'];
$count = db('menu')->where($map)->select();
$count = $count ? count($count) : $count;
if ($count) {
$menu = $this->setMenu($map, $menu, false);
}
}
}
return $menu;
}