树状结构的菜单和子菜单

时间:2018-09-19 10:30:25

标签: php laravel

我需要创建以下json格式的菜单。下面是我从中获取数据的表:-

id  title       parent_id   url
5   Dashboard   0           /dashboard 
6   Settings    0           /home 
7   Menu        6           /menu 
8   Menu Assign 6           /menu-assign 
9   Test        5           /test 
10  Demo        9           /demo

我的期望格式如下。

public tail = [
 {
   name: 'Dashboard',
   link: '/dashboard',
   child: [
     {
       name: 'Test',
       link: '/test',
       child: [
         {
           name: 'Demo',
           link: '/demo',
         }
       ]
     },
   ]
 },
 {
   name: 'Settings',
   link: '/settings',
   child: [
     {
       name: 'Menu',
       link: '/menu',
       child: []
     },
     {
       name: 'Menu Assign',
       link: '/menu-assign',
       child: []
     }
   ]
 }
];

我尝试了以下代码

public function menuTree($parent=0,$level=0){
        Global $menuArr;
        $menus = Menu::where('parent_id','=',$parent)->get();
        foreach($menus as $allMenu){
            $menuArr[$allMenu->id][$level] = str_repeat("-", $level).$allMenu->title;
            $level++;
            $this->menuTree($allMenu->id,$level);
            $level--;
        }
        return $menuArr;
    }

1 个答案:

答案 0 :(得分:0)

我还没有机会进行彻底的测试。但是,您可以使用collection实例遍历menu项。这必须通过几个步骤来实现。

  • 首先,我们需要创建一个$level公共变量,该变量可以在整个控制器类中使用。我们将其设置为menuTree()方法的开始。
  • $this->level = $this->level ?: $level将检查是否设置了$this->level变量并且该变量大于0。如果是这样,我们将假定它正在遍历树,否则只需将其设置为0。此ternary表达式与$this->level = $this->level ? $this->level : $level相同。
  • 继续,我们得到所有menus并使用map()收集助手来更改返回的结果。这是我们从名为menuItem()的新函数返回的地方。
  • menuItem()中,我们获得menu项目的namelink并将其添加到$data数组中。
  • 然后我们检查$this->level是否为true(如果大于0)。这样做是为了查看是否需要迭代子菜单项。我们还将检查是否存在任何menu项,这些项是当前菜单项的children。如果都成立,我们将再次循环执行此过程,并将级别数减少1

最后,如果$this->level大于0,则返回array,否则返回json数组。这是完成树和仍然在菜单级别进行迭代之间的区别。

这是完整的代码。

public $level;

public function menuTree($parent = 0, $level = 0)
{
    $this->level = $this->level ?: $level;

    $menus = Menu::where('parent_id', $parent)
        ->get()
        ->map(function ($menu, $key) {
            return $this->menuItem($menu);
        });

    return $this->level ? $menus->toArray() : $menus->toJson();   
}

public function menuItem($item)
{
    $data = [
        'name' => str_slug($item->title),
        'link' => $item->url,
    ];

    if ($this->level && Menu::where('parent_id', $item->id)->count()) {
        $data['child'] = $this->menuTree($item->id);
        $this->level--;
    }

    return $data;
}

注意:在将parent_id设置为null而不是0的情况下,您需要以不同的方式启动查询:

...

$menus = Menu::query();

if ($parent) {
    $menus = where('parent_id', $parent);
}

$menus = $menus->get()
    ->map(function ($menu, $key) {
        return $this->menuItem($menu);
    });

...

query()用于启动eloquent构建器。该条件设置为检查parent_id是否不是null|false|0,如果true,则应用查询。