Место для вас

Cоздание многоуровнего меню для Yii 2

Сегодня расскажу один секрет, как сделать многоуровневое меню для Yii, получая меню из базы данных.

В Yii за формирование меню отвечает готовый виджет. И чтоб сделать многоуровневое меню нужно просто рассписать все пункты руками. Это хорошо когда заранее известна структура меню и вы уверенны, что она изменяться уже не будет.

Но что делать если этого не известно??? Либо пытаться изобретать велосипед и самому создавать виджет. Лиюо качать готовые расширения для Yii и потом их править под свои нужды. Или воспользоваться моим протым решением, которое получает меню из БД и вставляем в готовый виджет меню от Yii.

Я не буду описывать, как добавить сам виджет для отображения меню. Тут кто как хочет так и делает.

Сделаю помарку: покажу пример для Yii 2

Сперва мы выводим меню:


use yii\widgets\Menu;
use app\models\TopMenu;
echo Menu::widget([
	'options' => ['class' => 'clearfix', 'id'=>'main-menu'],
	'encodeLabels'=>false,
	'activateParents'=>true,
	'activeCssClass'=>'current-menu-item',
	// подключаем модель и  вызываем метод,  который строит всю логику формирования меню
	'items' => app\models\TopMenu::viewMenuItems(),
]);

А вот сами  методы, которые делают всю работу и логику:


/***************START generate my top menu****************/
private static function getMenuItems()
{
	$items = array();
	$resultAll = TopMenu::find()->orderBy('position')->all();

	foreach($resultAll as $result)
	{
		if(empty($items[$result->parentid]))
		{
		$items[$result->parentid] = array();
		}
		$items[$result->parentid][] = $result->attributes;
	}
	return $items;
}

public static function viewMenuItems($parentId=0) { $arrItems = TopMenu::getMenuItems(); if(empty($arrItems[$parentId])) {return;} for($i = 0; $i<count($arrItems[$parentId]); $i++) { $result[] = [ 'label' => $arrItems[$parentId][$i]['name'], 'url' => [$arrItems[$parentId][$i]['seolink']], 'linkOptions'=> ['title'=>$arrItems[$parentId][$i]['name']], 'items' => TopMenu::viewMenuItems($arrItems[$parentId][$i]['id']), 'options' => ['class'=>$arrItems[$parentId][$i]['classa']], ]; } return $result; } /***************END generate my top menu****************/

Вот и все. за деталями обращайтесь в коментах =)

Как видно,  создание автоматического многоуровнего меню не так уж и сложно.


Место для вас

Коментарии

добавить коментарий

  1. Александр Булатов - 03 августа, 2017 в 08:39:39

    Спасибо огромное!

    Уже все способы перепробовал всю документацию наверно облазил, а Ваш способ отлично сделал свою работу!

    Ещё раз спасибо!

  2. Александр Булатов - 03 августа, 2017 в 08:39:36

    Только не могли бы Вы пояснить, почему срабатывает передача параметра $parentId = 0, ведь при итерации в цикле for он не увеличивается, а остаётся не изменным?

    • adminer - 03 августа, 2017 в 08:39:54

      Александр Булатов, спасибо. смотрите. в методе viewItems у мемя есть рекурсия. $parentId=0 указывает на супер главного родителя

    • Александр Булатов - 04 августа, 2017 в 14:08:32

      adminer, понял.


      А ещё один вопрос, если не возражаете, есть у Вас идеи, как в данном коде передать параметра, который бы ещё определял меню, которое нужно выводить?

      Я вот такой код добавил в метод getMenuItems




      $code = 'top-menu';


      $query_menu = MenuModel::find() ->andWhere(['code' => $code, 'status' => 1]) ->one();



      А выборку потом делаю с добавлением




      andWhere(['id' => $query_menu->id])



      Но выдаёт ошибку при передаче get-параметра.

    • adminer - 11 августа, 2017 в 13:17:59

      Александр Булатов, что за ошибка у вас?

  3. Александр Булатов - 15 октября, 2017 в 13:36:19

    Прошу прощения, что только сейчас написал.
    У меня получается следующим образом (названия функций и некоторые переменные я изменил):

    В отображении у меня сейчас так

    'items' => Choice_Menu::viewMenuItemsTop( 0, 'bottom-menu'),

     

    В методе viewMenuItemsTop

    public static function viewMenuItemsTop($parentId, $nameMenu)
    ,

    $array = self::getMenuItemsTop($nameMenu);


    А в методе

    private static function getMenuItemsTop($nameMenu)


    $code = $nameMenu;

            

            $query_menu = MenuModel::find()

                            ->andWhere(['code' => $code, 'status' => 1])

                            ->one();



    И в браузере такое сообщение

    issing argument 2 for app\modules\manager\models\Choice_Menu::viewMenuItemsTop(), called in C:\OpenServer\domains\yii2-cms-basic.loc\modules\manager\models\Choice_Menu.php on line 62 and defined

    И чтобы я не делал он всё равно говорит, что нехватает второго аргумента.

    • админер - 15 октября, 2017 в 13:38:25

      Александр Булатов, а можно в студию строку 62 ?

  4. Александр Булатов - 15 октября, 2017 в 16:21:30

    Строка 62 это строчка 

    'items' => self::viewMenuItemsTop($array[$parentId][$i]['id'])

    И чтобы был понятен контекст то полный код метода, где эта строчка

    public static function viewMenuItemsTop($parentId, $nameMenu)

        {        

            $array = self::getMenuItemsTop($nameMenu);

            

            if ( empty($array[$parentId]) ) { return; }

            

            for ( $i = 0; $i < count($array[$parentId]); $i++ )

            {

                $result[] = [

                    'label' => $array[$parentId][$i]['name'],

                    'url' => [$array[$parentId][$i]['url_item'].'/index'],

                    'items' => self::viewMenuItemsTop($array[$parentId][$i]['id'])

                ];

            }

            

            return $result;

        }

  5. Александр Булатов - 15 октября, 2017 в 16:21:32

    ))))
    Ну это я конечно выкинул)))
    Когда Вам написал, то увидел, где абсолютно глупая ошибка)

    Нужно вот так оформить 62 строчку:


    'items' => self::viewMenuItemsTop($array[$parentId][$i]['id'], $nameMenu)

    • админер - 15 октября, 2017 в 16:21:35

      Александр Булатов, ага. все верно. не хватало. успехов. будут вопросы, то обращайтесь

Добавить коментарий

кликните на картинку,
чтоб обновить код

Что за сайт

Этот сайт представляет унифицированную базу, где инфа собрана в единое целое, а не разбросанна по многочисленным сайтам, записям на листах бумаги или головам людей; а так же доступна круглосуточно не зависимо от кого-либо или чего-либо.

Будь в курсе

Интересненько

Вверх