Иногда возникает необходимость создавать меню самостоятельно, загружая его из базы данных. Сделать это можно рекурсивно. Не важно какой это будет фреймворк, это допустимо использовать и вне фреймворка.
Для создания Меню нужно лишь взять список пунктов из базы данных и сначала сформировать правильно массив, а затем из этого массива сформировать меню.
function prepareTree($items) { $arr = []; foreach($items as $item) { if (!$item->parent_id) $item->parent_id = 0; if(empty($arr[$item->parent_id])) $arr[$item->parent_id] = array(); $arr[$item->parent_id][] = $category; } return $arr; }
Функция prepareTree формирует массив, ключом которого будет id родительского меню.
Теперь переходим к рекурсивной функции, которая на основе созданного массива-дерева построит уже код меню для использования
function buildTree($arr, $parent_id = 0, &$str = '') { $menu = []; //условие выхода из рекурсии if (empty($arr[$parent_id])) { return; } if ($parent_id == 0) { $str .= '<ul class="main-menu">'; //Здесь, если хотите, можно добавить пункт меню Главная, если он не был определен пунктами из меню } else { $str .= '<ul>'; } for ($i = 0; $i < count($arr[$parent_id]); $i++) { if (!empty($arr[$arr[$parent_id][$i]->id])) { $str .= '<li class="menu-has-child">'; //проверяя существуют ли потомки, можно для li указать css-класс подменю } else { $str .= '<li>'; } $str .= Html::a($arr[$parent_id][$i]->name, $arr[$parent_id][$i]->url); self::buildTree($arr, $arr[$parent_id][$i]->id, $str); $str .= '</li>'; } $str .= '</ul>';
Функция, которая вызывает эти две функции для построения и вывода меню
public static function getMenu($items) { $string = ''; $menu = prepareTree($items); buildTree($menu, 0, $string); return $string; }
это функцию можно вывести например с помощью echo
$menu = Menu::find()->all(); echo getMenu($menu);
таким образом будет сформирован список меню, ul li, осталось прикрутить только классы стилей