Иногда возникает необходимость создавать меню самостоятельно, загружая его из базы данных. Сделать это можно рекурсивно. Не важно какой это будет фреймворк, это допустимо использовать и вне фреймворка.
Для создания Меню нужно лишь взять список пунктов из базы данных и сначала сформировать правильно массив, а затем из этого массива сформировать меню.
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, осталось прикрутить только классы стилей