继续上一篇,我们接着说yii2-admin中的menu。
传送门
Menu
接下来说一下菜单,我想这也是大家都很在意的一块。我们期望得到一种结果,当一个角色登陆后,ta只会看到和自己相关的菜单。
看看yii2-admin如何去实现~
为了更清晰的使用和理解,我们先构造一个权限系统作为例子,如图。
话说菜单也是需要配置的,打开yii2-admin的Menu,然后建立能被yii2-admin控制的菜单。
一个一个说吧
- ① 菜单的名字,这个不用多说了
- ② 父级,如果没有不用填写,有则写父级菜单名字
- ③ Route,这个是重要的,这些就是我们纳入了yii2-admin体系的路由列表,比如我本次的goods下的action
- ④ 排序,同级菜单的排序,按照所填数字从小向大升序来。
- ⑤ 数据,这里留坑,即将填。
我们新建了如下单的菜单
现在我们已经有了带角色功能的菜单,现在开始在视图中使用它。
使用菜单
好在yii2-admin提供了一个方法来获得某个角色的菜单数组
use mdm\admin\components\MenuHelper;MenuHelper::getAssignedMenu(Yii::$app->user->id)
我们使用MenuHelper来获得登录会员的角色菜单,它返回一个多维数组,如下面代码这样。
[ [ 'label' => $menu['name'], 'url' => [$menu['route']], 'items' => [ [ 'label' => $menu['name'], 'url' => [$menu['route']] ], .... ] ], [ 'label' => $menu['name'], 'url' => [$menu['route']], 'items' => [ [ 'label' => $menu['name'], 'url' => [$menu['route']] ] ] ], ....]
这个你熟悉吧,yii2的nav挂件需要的数组格式。
来实战下,在goods/index视图写如下代码
use mdm\admin\components\MenuHelper;\yii\helpers\VarDumper::dump(MenuHelper::getAssignedMenu(Yii::$app->user->id),10,true);die();
下面我们分别用 abei(master-role角色)和abei-kefu(kefu-role角色)登录,看看效果。
很高兴,从结果验证了yii2-admin很聪明的按照角色返回菜单数组了。
ok,现在我们回过头来说新建菜单时候的那个Data区域,我现在有个需求,刚才我建立了名字为goods、goods-index、goods-create的菜单,但是我不想这样显示,我希望在浏览器上的显示为“商品管理”、“商品列表”、“新建商品”。
用Data区域就可以实现此目的。
当然核心是用yii2-admin对MenuHelper::getAssignedMenu返回的菜单数组进行格式化的功能,那开始吧,只需在goods/index的视图里增加一个回调函数,如下
use mdm\admin\components\MenuHelper;$callback = function($menu){ $data = $menu['data']; return [ 'label' => $data ? $data : $menu['name'], 'url' => [$menu['route']], 'items' => $menu['children'] ];};$items = MenuHelper::getAssignedMenu(Yii::$app->user->id, null, $callback);\yii\helpers\VarDumper::dump($items,10,true);die();
其中的$menu['data']就是我们填写的值,当然其实这个区域可以填写更多复杂的东东(比如一句PHP语句)。我的逻辑很简单,对于每一个菜单项,如果有设置data值,则用data值替代name成为显示的label,否则还是用name;
看看结果吧
又学会了一点点,继续往下,到现在我们得到了一个数组,下面来做一个实际效果,将这个数组弄到yii2的菜单中
// view/goods/indexuse mdm\admin\components\MenuHelper;use yii\bootstrap\Nav;$callback = function($menu){ $data = $menu['data']; return [ 'label' => $data ? $data : $menu['name'], 'url' => [$menu['route']], 'items' => $menu['children'] ];};$items = MenuHelper::getAssignedMenu(Yii::$app->user->id, null, $callback);echo Nav::widget(['items'=>$items]);
好,就是我想要的。到此刻我们构造出了一个二维的菜单,当然多维也是一样的逻辑,这里还要说一个地方。
getAssignedMenu
要说的是这个函数的第二个参数,默认为null,获取整个菜单结构,当我们为其传递一个菜单节点的时候,则可以获得该节点的子菜单。
但是要注意的是:参数值是节点菜单的ID,而不是name,这点要切记。
另一种情况
我们前面是通过登陆会员得到对应菜单数组然后渲染,在世界上还有一种情景就是一个完整的菜单就放到那里,会员登陆后筛选出自己的部分。
好在yii2-admin也可以帮我们实现,我们来code下。
use mdm\admin\components\Helper;// 完整的菜单$menuItems = [ ['label' => '', 'url' => ['/site/index']], ['label' => 'About', 'url' => ['/site/about']], ['label' => 'Contact', 'url' => ['/site/contact']], ['label' => '商品管理', 'items' => [ ['label' => '商品列表', 'url' => ['/goods/index']], ['label' => '新建商品', 'url' => ['/goods/create']], ]]];$menuItems = Helper::filter($menuItems);echo Nav::widget([ 'options' => ['class' => 'navbar-nav navbar-right'], 'items' => $menuItems,]);
我们通过Helper::filter函数对其进行了筛选,看看结果
从结果你应该能知道,这是一次非常严格的筛选,首先要根据yii2-admin设置的menu匹配,然后你还要有权限的才会显示,很严格。
关于Helper::checkRoute
从上面的例子我们知道在视图里主要靠 mdmadmincomponentsHelper 来搞定这些事情,它还提供了一个checkRoute,参数是一个路由,用来判断当前会员是否对某个路由有权限,比如如下代码
use mdm\admin\components\Helper;if(Helper::checkRoute('/goods/delete')){ //...}
到此刻位置,yii2-admin关于menu的使用就完事了,当然细节还有不少,以后慢慢慢说。
关于按钮
当我们使用GridView的时候,一般最后一列都是一对action按钮,那么不同的角色对这些按钮可能操作权限是不同的,yii2-admin也为我们提供了这个场景的筛选,见代码
use mdm\admin\components\Helper;'columns' => [ ... [ 'class' => 'yii\grid\ActionColumn', 'template' => Helper::filterActionColumn('{view}{delete}{posting}'), ]]
对,使用 Helper::filterActionColumn就可以,当然你在GridView的buttons里用Helper::checkRoute来判断我也没意见,喜欢哪个用哪个。
总结下
到此刻为止,我们用3篇把yii2-admin官方的文档 + 一点小例子就算说完了,算是一个入门级的中文文档,接下来我们会对这个扩展那些细节配置及实际使用中的情景进行解说,明天继续聊。