меню и подменю в древовидной структуре - PullRequest
0 голосов
/ 19 сентября 2018

Мне нужно создать меню в формате ниже 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 голосов
/ 19 сентября 2018

У меня не было возможности тщательно это проверить.Однако вы можете использовать экземпляр 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 элементов name и link и добавляем их в массив $data.
  • Затем мы проверяем, является ли $this->level true (если больше 0).Это делается для того, чтобы увидеть, нужно ли выполнять итерации для дочерних пунктов меню.Мы также проверяем, существуют ли элементы menu, в которых children текущего элемента меню.Если оба значения равны true, мы снова выполняем цикл и уменьшаем количество уровней на 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.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...