Yii Framework, меню сайта с использованием виджета CMenu (zii.widgets.CMenu)

Редко можно встретить сайт без меню. Меню присутствует практически на любом сайте, этот факт разработчики Yii Framework учли при разработке фреймворка. В Yii есть виджет CMenu (zii.widgets.CMenu) для создания меню сайта. По умолчанию этот виджет уже используется при создании нового проекта на Yii (в тестовом примере). Выглядит он примерно так:

<?php
$this->widget('zii.widgets.CMenu',array(
    'items'=>array(
        array('label'=>'Home', 'url'=>array('/site/index')),
        array('label'=>'About', 'url'=>array('/site/page', 'view'=>'about')),
        array('label'=>'Contact', 'url'=>array('/site/contact')),
        array('label'=>'Login', 'url'=>array('/site/login'), 'visible'=>Yii::app()->user->isGuest),
        array('label'=>'Logout ('.Yii::app()->user->name.')', 'url'=>array('/site/logout'), 'visible'=>!Yii::app()->user->isGuest)),
    )
); 

Пример виджет CMenu с настройками под стиль bootstrap

И так давайте рассмотрим более сложный пример меню с использованием стилей bootstrap и содержащим подменю:

<?php
$this->widget('zii.widgets.CMenu', array(
    'htmlOptions' => array('class' => 'nav navbar-nav'),
    //разрешим HTML-теги в пунктах меню
    'encodeLabel' => false,
    'items' => array(
        array(
            'label' => 'Главная',
            'url' => array(
                '/site/index'
            ),
        ),
        array(
            'label' => 'Статьи',
            'url' => array(
                '/posts/default/index'
            ),
            //подсвечивать этот пункт меню, если мы находимся в модуле posts 
            //(например, в списке статей, в подробном описании, ...)
            'active' => (isset(Yii::app()->controller->module->id) && Yii::app()->controller->module->id == 'posts'),
        ),
        array(
            'label' => 'Новости',
            'url' => array(
                '/news/index'
            ),
            //подсвечивать этот пункт меню, если мы находимся в контроллере news
            //(например, в списке новостей, в подробном описании новости, ...)
            'active' => (Yii::app()->controller->id == 'news'),
        ),
        array(
            'label' => 'О нас',
            'url' => array(
                '/site/about'
            ),
        ),
        array(
            'label' => 'Обратная связь',
            'url' => '#',
            //добавим атрибуты к нашей ссылке 
            //(для работы bootstrap модального окна)
            'linkOptions' => array(
                'data-toggle' => 'modal',
                'data-target' => '#fbModal'
            ),
        ),                    
        array(
            //выводить этот пункт меню только для авторизированного пользователя
            //(так же можно выводить пункты меню в зависимости от прав(ролей) пользователя)
            'visible' => !Yii::app()->user->isGuest,
            //здесь присутствуют html теги
            //(их вывод мы включили с помощью свойства 'encodeLabel' => false)
            'label' => (!empty(Yii::app()->user->title) ? Yii::app()->user->title : '') . ' <span class="caret"></span>',
            'active' => (isset(Yii::app()->controller->module->id) && Yii::app()->controller->module->id == 'user'),
            'url' => '#',
            //установим класс для контейнера подменю
            'submenuOptions' => array(
                'class' => 'dropdown-menu'
            ),
            //установим дополнительные HTML-атрибуты тега <a> для подменю
            'linkOptions' => array(
                'class' => 'dropdown-toggle',
                'data-toggle' => 'dropdown',
                'role' => 'button',
                'aria-haspopup' => 'true',
                'aria-expanded' => 'false'
            ),
            //список пунктов подменю
            'items' => array(
                array(
                    //при необходимости здесь мы можем использовать свойства active, visible и т.д.
                    'label' => 'Профиль',
                    'url' => array(
                        '/user/profile/index'
                    ),
                    //при желании можно добавит еще один уровень меню
                    //'items' => array(),
                ),
                array(
                    'label' => 'Избранное',
                    'url' => array(
                        '/user/favorites/index'
                    ),
                ),
                array(
                    'label' => '',
                    'itemOptions' => array(
                        'role' => 'separator',
                        'class' => 'divider'
                    ),
                ),
                array(
                    'label' => 'Выход',
                        'url' => array(
                            '/site/logout'
                        ),
                    ),
                ),
            ),
        ),
        //...
    ),
);

Естественно такой массив мы можем создать с помощью цикла, взяв данные из БД или любого другого источника.

Подправим urlManager для красивого отображения url, /protected/config/main.php:

<?php
return array(
    //...
    'components' => array(
        //...
        'urlManager' => array(
            'urlFormat' => 'path',
            'showScriptName' => false,
            'rules' => array(
                //...
                '/' => 'site/index',
                '/posts' => 'posts/default/index',
                '/posts/' => 'posts/default/detail',
                '/news' => 'news/index',
                '/news/' => 'news/detail',
                '/logout' => 'site/logout',
                '/user/profile' => 'user/profile/index',
                '/user/favorites' => 'user/favorites/index',                
                '<controller:\w+>/<id:\d+>' => '<controller>/view',
                '<controller:\w+>/<action:\w+>/<id:\d+>' => '<controller>/<action>',
                '<controller:\w+>/<action:\w+>' => '<controller>/<action>',
                //...
            ),
            //...
        ),     
        //...
    ),
    //...
);

Основные свойства виджета CMenu

Для более тонкой настройки виджета CMenu (zii.widgets.CMenu) Вы можете использовать следующие свойства:

Свойство Тип Описание
activeCssClassstringCSS класс, который будет добавлен в активный пункт меню.
encodeLabelbooleanУказывает разрешить ли HTML-теги в пунктах меню (label). По умолчанию запрещено (false)
firstItemCssClassstringCSS класс для первого пункта меню или каждого первого пункта подменю.
htmlOptionsarrayHTML атрибуты для главного контейнера меню
itemCssClassstringCSS класс, который будет присвоен каждому пункту меню.
itemTemplatestringшаблон, используемый для отображения отдельного элемента меню.
itemsarrayСписок пунктов меню.
lastItemCssClassstringCSS класс, для последнего пункта в меню или каждого последнего пункта подменю.
linkLabelWrapperstringHTML-тег, который будет использоваться для обвертывания ссылок меню.
linkLabelWrapperHtmlOptionsarrayАтрибуты HTML для обертывания элемента ссылки, которые указанны в свойстве linkLabelWrapper.
submenuHtmlOptionsarrayАтрибуты HTML для тега контейнера подменю

Свойства элемента items

Описание свойств элемента items виджета CMenu (zii.widgets.CMenu) для более тонкой настройки подменю:

Свойство Тип Описание
labelstringМетка пункта меню (название пункта меню)
encodeLabelbooleanУказывает разрешить ли HTML-теги в пунктах меню (label), она перекрывает глобальные настройки свойства encodeLabel.
urlstring | arrayСсылка (url) для пункта меню
visiblebooleanОтображать ли текущий пункт меню. По умолчанию отображать (true). Это свойство может быть использовано для управления отображения пункта меню на основе прав пользователей (ролей).
itemsarrayМассив элементов подменю. Формат такой же, как и у родительского элемента.
activebooleantrue указывает, на то что этот пункт меню находится в активном состоянии (в настоящее время выбран). Если пункт меню активен и activeClass не является пустым, его класс CSS будет добавлен с activeClass. Если эта опция не установлена, элемент меню будет установлен активным автоматически, когда текущий запрос инициируется URL.
templatestringШаблон отображения этого пункта меню. Когда эта опция установлена, она перекрывает глобальные настройки ItemTemplate.
linkOptionsarrayДополнительные HTML-атрибуты для ссылки(тег <a>) пункта меню.
itemOptionsarrayДополнительные HTML-атрибуты для контейнера пункта меню.
submenuOptionsarrayДополнительные HTML-атрибуты для контейнера подменю, если есть подменю. Когда эта опция установлена, то свойство submenuHtmlOptions будет игнорироваться для данного подменю.

Все свойства виджета CMenu (zii.widgets.CMenu) Вы можете посмотреть на официальном сайте Yii Framework: http://www.yiiframework.com/doc/api/1.1/CMenu.