如何在YII2中构建动态菜单

时间:2015-12-03 07:26:12

标签: yii2-advanced-app

我希望根据用户的权限拥有动态菜单。例如,管理员帐户和基本帐户都有一个菜单。

我目前正在执行以下操作。

          <?php

            if((yii::$app->user->can('admin')) || (yii::$app->user->can('blah')) || (yii::$app->user->can('blahblah'))) ..and so on
            {
                //..print the menu 
            }

            //another condition for menu here.
            ?>

如果有条件,是否有快捷方式? 例如,我声明一个内部具有权限的数组,然后我将使用in_array方法检查用户是否有权查看链接。

4 个答案:

答案 0 :(得分:3)

Yii2模板附带Bootstrap 3,Nav小部件最常用于构建菜单。

以下是动态声明菜单项可见性的示例:

echo Nav::widget([
    'options' => ['class' => 'navbar-nav navbar-right'],
    'items' => [
        [
            'label' => 'Users',
            'url' => ['/users'],
            'visible' => Yii::$app->user->can('users.manage'),
        ],

        ...
    ],
]);

您不需要检查每个可能的角色,您需要检查访问/管理特定部分的权限。

例如,在提供的示例中,具有指定权限users.manage的每个用户都可以查看该菜单项。因此,添加permssion并将其分配给所需的用户角色。

不要忘记检查控制器中的权限,如果链接仍然可访问,将其隐藏在布局中是没有意义的。

有时您拥有带有分组项目的嵌套子菜单,并且您希望有条件地显示它,具体取决于权限。你可以这样做:

$menuItems = [
    [
        'label' => 'Section',
        'items' => [
            [
                'label' => 'Subsection One',
                'url' => ['/sub-section-one/index']],
                'visible' => Yii::$app->user->can('sub-section-one.manage'),
            ],
            [
                'label' => 'Subsection One',
                'url' => ['/sub-section-one/index']],
                'visible' => Yii::$app->user->can('sub-section-two.manage'),
            ],
        ],
    ],
],

echo Nav::widget([
    'options' => ['class' => 'navbar-nav navbar-right'],
    'items' => $menuItems,
]);

问题是,如果用户没有管理两个子部分的权限,则用于分组的根部分仍然可见。我们显然可以添加

'visible' => Yii::$app->user->can('sub-section-one.manage') || Yii::$app->user->can('sub-section-two.manage'),

但是如果RBAC authManagerDbManager且关闭了缓存,则会执行其他查询,我们会复制代码。

所以你可以这样做:

$sectionItems => [
    [
        'label' => 'Subsection One',
        'url' => ['/sub-section-one/index']],
        'visible' => Yii::$app->user->can('sub-section-one.manage'),
    ],
    [
        'label' => 'Subsection One',
        'url' => ['/sub-section-one/index']],
        'visible' => Yii::$app->user->can('sub-section-two.manage'),
    ],
],

$isSectionVisible = false;

foreach ($sectionItems as $sectionItem) {
    if ($sectionItem['visible']) {
        $isSectionVisible = true;

        break;
    }
}

然后:

$menuItems = [
    [
        'label' => 'Section',
        'visible' => $isSectionVisible,
        'items' => $sectionItems,
    ],
],

echo Nav::widget([
    'options' => ['class' => 'navbar-nav navbar-right'],
    'items' => $menuItems,
]);

或者您可以扩展Nav窗口小部件并实现此逻辑。

另请查看高级模板layout,还有一个构建动态菜单的示例:

$menuItems = [
    ['label' => 'Home', 'url' => ['/site/index']],
];
if (Yii::$app->user->isGuest) {
    $menuItems[] = ['label' => 'Login', 'url' => ['/site/login']];
} else {
    $menuItems[] = '<li>'
        . Html::beginForm(['/site/logout'], 'post')
        . Html::submitButton(
            'Logout (' . Yii::$app->user->identity->username . ')',
            ['class' => 'btn btn-link']
        )
        . Html::endForm()
        . '</li>';
}
echo Nav::widget([
    'options' => ['class' => 'navbar-nav navbar-right'],
    'items' => $menuItems,
]);

答案 1 :(得分:0)

使用它:动态2级菜单项yii2

$menuItems = array();
                $pages_record = Pages::find()->all();
                $i = 0;
                foreach ($pages_record as $data) 
                {
                    if($data->select_parent == 0)
                    {
                        $path = \Yii::$app->request->BaseUrl."/index.php?r=".$data->seo_url;
                        $menuItems[$i] = array('label' => $data->page_title, 'url' => $path);
                        $pages_sub_rec = Pages::findAll(['select_parent' => $data['pid']]);
                        foreach ($pages_sub_rec as $sub_value)
                        {
                            $menuItems[$i]['items'][] = array('label' => $sub_value->page_title, 'url' => '#');
                        }
                        $i++;
                    }
                }

答案 2 :(得分:0)

我闷闷不乐

composer requiere pceuropa/yii2-menu dev-master

答案 3 :(得分:-1)

我用一个简单的方法 DB:menu and childmenu
加入:menu_id(childmenu)到id(菜单)

``

<ul>
      $mainmenu = \common\models\Menu::find()->all();
                foreach ($mainmenu as $data)
      {
          echo "<li><a  href='$data->url'>$data->name_en</a><ul>";
          $sub_menu = \common\models\Childmenu::find()->where(['menu_id'=>$data->id])->all();
          foreach ($sub_menu as $sub_value)
          {
              echo "<li><a  href='$sub_value->url'>$sub_value->name_en</a></li>";
          }
          echo "</ul></li>";
      }
?></ul>

```