2015-01-14 10:40:20 10098次浏览 4条回答 0 悬赏 5 金钱

配置步骤:
1.首先我们要在 组件里面配置一下 Rbac

'authManager' => [
  'class' => 'yii\rbac\DbManager',
],

2.yii migrate --migrationPath=@yii/rbac/migrations/
运行此命令生成权限数据表
3.Rbac.php类如下:主要是将DbManager类里一些封装的方法公开。

namespace app\models;

use yii\rbac\DbManager;
class Rbac extends DbManager{
        
        public function createItem($item){
                
                if(empty($item->name) || $this->getOneItem($item->name) !== null)
                        return false;
                return $this->addItem($item) ? true : false;
                
        }
        
        public function getOneItem($name){
                return $this->getItem($name);
        }
        
        public function updateOneItem($name, $item){
                
                return $this->updateItem($name, $item);
        }
        
        public function deleteOneItem($name){
                
                if($item = $this->getOneItem($name))
                        return $this->removeItem($item);
                else 
                        return false;
                
        }
        
}

4.RbacController.php 主要实现了基础的RBAC数据写入查看功能

namespace backend\controllers;

use yii\db\Query;
use yii\data\ActiveDataProvider;
class RbacController extends BaseController{
        /**
         * 角色/权限列表
         * @param number $type
         * @return Ambigous <string, string>
         */
        public function actionItemindex($type = 1){
                $auth = \Yii::$app->getAuthManager();
                $dataProvider = new ActiveDataProvider([
                        'query' => (new Query())->from($auth->itemTable)
                                                                        ->where(['type'=>$type])
                                                                        ->orderBy(['created_at'=>SORT_DESC]),
                        'pagination' => ['pageSize' => 8],
                ]);
                return $this->render('itemIndex',['dataProvider'=>$dataProvider,'type'=>$type]);
        }
        
        /**
         * 添加角色/权限
         * @param unknown $type
         * @return Ambigous <string, string>
         */
        public function actionCreateItem($type){
                
                $item = new \yii\rbac\Item();
                
                if($item->name === null  && ($data = \Yii::$app->request->post())){
                        $item->name = $data['name'];
                        $item->description = $data['description'];
                        $item->ruleName = $data['ruleName'];
                        $item->data = $data['data'];
                        $item->type = $type;
                        
                        $rbac = \Yii::$container->get('\app\models\Rbac');
                        if($rbac->createItem($item))
                                return $this->success(['view-item','name'=>$item->name]);        
                        else
                                return $this->error('数据插入失败!');
                        
                }
                return $this->render('_itemform',['model'=>$item,'type'=>$type]);
                
        }
        /**
         * 更新一个 角色/权限
         * @param unknown $name
         * @return Ambigous <\backend\controllers\Ambigous, string, string>|Ambigous <string, string>
         */
        public function actionUpdateItem($name){
                $rbac = \Yii::$container->get('\app\models\Rbac');
                if(empty($item = $rbac->getOneItem($name)))
                        return $this->error('不存在的项目');
                if($data = \Yii::$app->request->post()){
                        $name = $item->name;
                        $item->name = $data['name'];
                        $item->description = $data['description'];
                        $item->ruleName = $data['ruleName'];
                        $item->data = $data['data'];
                        
                        if($rbac->updateOneItem($name,$item))
                                return $this->success(['view-item','name'=>$item->name]);
                        else
                                return $this->error('数据修改失败!');
                        
                }
                return $this->render('_itemform',['model'=>$item,'type'=>$item->type]);
                
        }
        /**
         * 删除一个角色 权限
         * @param unknown $name
         * @return Ambigous <\backend\controllers\Ambigous, string, string>
         */
        public function actionDeleteItem($name){
                $rbac = \Yii::$container->get('\app\models\Rbac');
                //使用了MyISAM引擎,因此不支持级联删除,所以不允许有子节点的情况下删除父节点
                if((new Query())->from($rbac->itemChildTable)->andWhere(['parent'=>$name])->orWhere(['child'=>$name])->count()>0)
                        return $this->error('该项目下还有子节点,请先删除子节点再删除该节点'); 
                if($rbac->deleteOneItem($name))
                        return $this->success(['itemindex']);
                else
                        return $this->error('删除失败!');
        }
        /**
         * 查看信息 角色  权限
         * @param unknown $name
         * @return Ambigous <string, string>
         */
        public function actionViewItem($name){
                $rbac = \Yii::$container->get('\app\models\Rbac');
                $item = $rbac->getOneItem($name);
                if($item !== null)
                        return $this->render('itemView',['model'=>$item]);
                else
                        $this->goBack();
        }
        
        /**
         * Ajax判断角色 权限是否存在主键冲突
         * @return string
         */
        public function actionAjaxIshasItem(){
                $data = \Yii::$app->request->post();
                $rbac = \Yii::$container->get('\app\models\Rbac');
                
                $result = $rbac->getOneItem($data['name']);
                if($data['name'] == $data['newRecord'])
                        return json_encode($result === null ? false:true);
                else 
                        return json_encode($result === null ? true:false);
        }
        
        /**
         * 子节点列表
         * @return Ambigous <string, string>
         */
        public function actionItemChildindex(){
                $auth = \Yii::$app->getAuthManager();
                $dataProvider = new ActiveDataProvider([
                        'query' => (new Query())->from($auth->itemChildTable)
                                                                        ->orderBy(['parent'=>SORT_DESC]),
                ]);
                
                return $this->render('itemChildIndex',['dataProvider'=>$dataProvider]);
        }
        
        /**
         * 添加子节点  可以为角色 权限添加子节点  (不能将一个权限作为角色的子节点 )
         */
        public function actionCreateItemChild(){
                
                if($data = \Yii::$app->request->post()){
                        $rbac = \Yii::$container->get('\app\models\Rbac');
                        if(empty($data['parent']) || empty($data['childs']) || !($parent = $rbac->getOneItem($data['parent']))) 
                                return $this->error('父节点或子节点信息错误!');
                        $errors = 0;
                        foreach ($data['childs'] as $v){
                                if(!($child = $rbac->getOneItem($v)))
                                        return $this->error('不存在的子节点!');
                                try {
                                        $rbac->addChild($parent,$child);
                                }catch (\Exception $e){
                                        $errors++;
                                }                                
                        }
                        
                        if($errors)
                                return $this->success(['item-childindex'],$errors.'条信息没有插入成功');
                        else 
                                return $this->success(['item-childindex']);
                        
                }

                return $this->render('_itemChildForm',['model'=>['parent'=>'','child'=>'']]);
        }
        
        /**
         * 删除子节点
         * @param unknown $parent
         * @param unknown $child
         * @return Ambigous <\backend\controllers\Ambigous, string, string>
         */
        public function actionDeleteItemChild($parent,$child){
                $rbac = \Yii::$container->get('\app\models\Rbac');
                if(empty($parent) || empty($child) || !($parent = $rbac->getOneItem($parent)) || !($child = $rbac->getOneItem($child)))
                        return $this->error('错误的参数');
                return $rbac->removeChild($parent, $child) ?  $this->success(['item-childindex']) : $this->error('删除失败');
                
        }
        /**
         * Ajax请求所有的项目
         */
        public function actionAjaxGetAllitem(){
                $auth = \Yii::$app->getAuthManager();
                $items = (new Query)->select(['name','description','type'])->from($auth->itemTable)->orderBy(['type'=>SORT_ASC])->all($auth->db);
                
                return $this->renderAjax('itemViewAll',['data'=>$items]);
                
        }
        
        /**
         * 用户权限列表
         */
        public function actionAssignmentIndex(){
                $auth = \Yii::$app->getAuthManager();
                return $this->render('assignmentIndex',['data'=>(new Query())->from($auth->assignmentTable)->orderBy(['user_id'=>SORT_DESC])->all()]);
                
        }
        /**
         * 为用户分配角色
         */
        public function actionCreateAssignment(){
                
                $rbac = \Yii::$container->get('\app\models\Rbac');
                if(($data = \Yii::$app->request->post()) && !empty($data['user_id']) && !empty($data['item_name'])){
                        $item = $rbac->getOneItem($data['item_name']);
                        $role = new \yii\rbac\Role();
                        if(empty($item))
                                return $this->error('错误的传入参数');
                        $role->name = $item->name;
                        
                        if($rbac->assign($role,$data['user_id']))
                                return $this->success(['assignment-index']);
                        else 
                                return $this->error('分配权限失败');
                        
                }
                $arr = array_combine((new Query())->select(['name'])->from($rbac->itemTable)->where(['type'=>1])->orderBy(['name'=>SORT_DESC])->column(), (new Query())->select(['description'])->from($rbac->itemTable)->where(['type'=>1])->orderBy(['name'=>SORT_DESC])->column());
                return $this->render('_assignment',['roles'=>$arr]);
                
        }
        /**
         * 删除用户角色
         * @param unknown $user_id
         * @param unknown $item_name
         */
        public function actionDeleteAssignment($user_id,$item_name){
                
                $rbac = \Yii::$container->get('\app\models\Rbac');
                $item = $rbac->getOneItem($item_name);
                
                if($rbac->revoke($item, $user_id))
                        return $this->success(['assignment-index']);
                else
                        return $this->error('删除失败');
        }
        
}

5.几个视图类文件,_itemform.php

<?php
use yii\helpers\Html;
use yii\helpers\Url;
?>
<div style="width:100%;margin:0 25%;">
        <div class="list-group col-md-6">
        <?php echo empty($model->name) ? Html::beginForm([ 'create-item','type'=>$type],'post') :
                                                                         Html::beginForm(['update-item','name'=>$model->name],'post');?>
                <div class="list-group-item"><?php echo empty($model->name) ? '添加':'修改';?><?php echo $type==1?'角色':'权限';?></div>
                <div class="list-group-item"><?php echo Html::label('名称:',null,['class'=>'col-md-3']).Html::textInput('description',$model->description);?></div>
                <div class="list-group-item">
                        <?php echo Html::label('标 识:',null,['class'=>'col-md-3']).Html::textInput('name',$model->name,['id'=>'itemName']);?>
                        <div id="item-name-error" class="col-md-offset-3"></div>
                </div>
                <div class="list-group-item"><?php echo Html::label('规则名称:',null,['class'=>'col-md-3']).Html::textInput('ruleName',$model->ruleName);?></div>
                <div class="list-group-item"><?php echo Html::label('数据:',null,['class'=>'col-md-3']).Html::textInput('data',$model->data);?></div>
                <div class="list-group-item">
                        <?php echo Html::button(empty($model->name)? '添加信息':'修改信息',['type'=>'submit','class'=>'btn btn-success col-md-offset-4']);?>
                        <input type="button" value="返回上一页" onclick="history.go(-1);" class="btn btn-default" />
                </div>
        <?php echo Html::endForm();?>
        </div>
</div>
<script>
<?php $this->beginBlock('JS_END');?>

        $('#itemName').blur(function(){
                        if($('#itemName').val() == ''){
                                alert('标识必须填写');
                                return;
                        }
                                
                        $.ajax({
                                url:'<?php echo Url::to(['ajax-ishas-item']);?>',
                                data:{'name':$('#itemName').val(),'newRecord':'<?php echo empty($model->name) ? '':$model->name; ?>'},
                                dataType:'json',
                                type:'post',
                                success: function(result){
                                                if(result)
                                                        $('#item-name-error').css('color','green').html('该标识可以使用!');        
                                                else
                                                        $('#item-name-error').css('color','red').html('该标识已使用,请修改标识!');
                                        }
                                });
                });
<?php 
$this->endBlock();
$this->registerJs($this->blocks['JS_END'],\yii\web\view::POS_END);
?>
</script>

角色或权限查看的视图:itemIndex.php

<?php
use yii\grid\GridView;
use yii\helpers\Html;

echo  Html::a($type == 1 ?'添加角色':'添加权限',['create-item','type'=>$type],['class'=>'btn btn-success']);


echo GridView::widget([
        'dataProvider' => $dataProvider,
        'columns' =>[
                        ['class' => 'yii\grid\SerialColumn'],
                        'description:text:名称',
            'name:text:标识',
                        ['attribute'=>'type','label'=>'类型','value'=>function($model, $key, $index, $column){if($model['type']==1)return '角色'; else return '权限';}],
            'rule_name:text:规则名称',
            'created_at:date:创建日期',
            'updated_at:date:修改时间',

            [
                    'class' => 'yii\grid\ActionColumn',
                                'header' => '操作',
                                'template' => '{view}  {update}  {delete}',
                                'buttons' => [
                                      'view' => function ($url, $model, $key) {
                                                  return  Html::a('查看',['view-item','name'=>$model['name']]);
                                             },
                                           'update' => function ($url, $model, $key) {
                                                        return  Html::a('更新',['update-item','name'=>$model['name']]);
                                             },
                                           'delete' => function ($url, $model, $key) {
                                                     return  Html::a('删除',['delete-item','name'=>$model['name']]);
                                             }
                                ]
                        ]
        ],
        
        'layout' => "\n{items}\n{summary}{pager}",
        
]);

子节点的创建视图:_itemChildForm.php 使用了Ajax刷新节点列表

<?php
use yii\helpers\Html;
use yii\helpers\Url;
?>
<div style="width:100%;margin:0 5%;">
        <div class="list-group col-md-10">
        <?php echo Html::beginForm(['create-item-child'],'post');?>
                <div class="list-group-item">
                        <?php echo Html::label('父节点:',null,['class'=>'col-md-3']).Html::textInput('parent',$model['parent'],['id'=>'parent-item-value']);?>
                        <span class="glyphicon glyphicon-plus btn" id="parent-node"></span>
                </div>
                <div class="bg-success" id="parent-node-contents"></div>
                <div class="list-group-item">
                        <?php echo Html::label('子节点:',null,['class'=>'col-md-3'])?>
                        <span class="glyphicon glyphicon-plus btn" id="child-node"></span>
                </div>
                <div id="child-node-contents"></div>
                <div class="list-group-item">
                        <?php echo Html::button(empty($model['parent'])? '添加信息':'修改信息',['type'=>'submit','class'=>'btn btn-success col-md-offset-4']);?>
                        <input type="button" value="返回上一页" onclick="history.go(-1);" class="btn btn-default" />
                </div>
        <?php echo Html::endForm();?>
        </div>
</div>
<script>
<?php $this->beginBlock('GET_ITEM_NODE');?>
        $('#parent-node').click(function(){
                if($('#parent-node-contents').html() == ''){
                        $.ajax({
                                url:'<?php echo Url::toRoute(['ajax-get-allitem'])?>',
                                type:'get',
                                success:function(data){
                                                $('#parent-node-contents').html(data);
                                                $('#parent-node').removeClass('glyphicon glyphicon-plus');
                                                $('#parent-node').addClass('glyphicon glyphicon-minus');
                                                //为每个子节点绑定事件
                                                $('#parent-node-contents table tr td').click(function(){
                                                        $('#parent-item-value').val($(this).find('strong').html());
                                                        $(this).siblings().removeClass('bg-info');
                                                        $(this).addClass('bg-info');
                                                        }).css('cursor','pointer');
                                        }
                                });
                }else{
                        if($('#parent-node-contents').css('display') == 'none'){
                                $('#parent-node-contents').css('display','');
                                $('#parent-node').removeClass('glyphicon glyphicon-plus');
                                $('#parent-node').addClass('glyphicon glyphicon-minus');
                        }else{
                                $('#parent-node-contents').css('display','none');
                                $('#parent-node').removeClass('glyphicon glyphicon-minus');
                                $('#parent-node').addClass('glyphicon glyphicon-plus');
                        }
                }
        });

        $('#child-node').click(function(){
                if($('#child-node-contents').html() == ''){
                        if($('#parent-node-contents').html() == '')
                                return alert('请先选择父节点');
                        $('#child-node').removeClass('glyphicon glyphicon-plus');
                        $('#child-node').addClass('glyphicon glyphicon-minus');
                        $('#child-node-contents').html($('#parent-node-contents').html());
                        //取消所有绑定事件
                        $('#child-node-contents table tr td').unbind("click").css('cursor','pointer').removeClass('bg-info');
                        //添加CHECK BOX
                        $('#child-node-contents table tr td span').before('<input type="checkbox" name="childs[]" class="child-items" value="" />  ');
                        //绑定点击事件
                        $('#child-node-contents table tr td').click(function(){
                                var childValueObj = $(this).find('.child-items');
                                if(childValueObj.val() == '')
                                        childValueObj.val($(this).find('strong').html());
                                if(childValueObj.prop('checked')){
                                        childValueObj.prop('checked',false)
                                        $(this).removeClass('bg-info');
                                }else{
                                        //判断添加关系
                                        if($('#parent-item-value').val() == childValueObj.val())
                                                return alert('不能为自己添加子节点');
                                        if($("#parent-node-contents table tr td strong:contains('"+$('#parent-item-value').val()+"')").attr('type') == 2 && $(this).find('strong').attr('type') == 1)
                                                return alert('不能将角色作为权限的子节点');
                                        
                                        childValueObj.prop('checked',true)
                                        $(this).addClass('bg-info');
                                }
                        });
                }else{
                        if($('#child-node-contents').css('display') == 'none'){
                                $('#child-node-contents').css('display','');
                                $('#child-node').removeClass('glyphicon glyphicon-plus');
                                $('#child-node').addClass('glyphicon glyphicon-minus');
                        }else{
                                $('#child-node-contents').css('display','none');
                                $('#child-node').removeClass('glyphicon glyphicon-minus');
                                $('#child-node').addClass('glyphicon glyphicon-plus');
                        }
                }
        });

        
<?php $this->endBlock();
$this->registerJs($this->blocks['GET_ITEM_NODE'],\yii\web\View::POS_END);
?>
</script>

数据表结构:

`CREATE TABLE `auth_item` (
  `name` varchar(64) COLLATE utf8_unicode_ci NOT NULL,
  `type` int(11) NOT NULL,
  `description` text COLLATE utf8_unicode_ci,
  `rule_name` varchar(64) COLLATE utf8_unicode_ci DEFAULT NULL,
  `data` text COLLATE utf8_unicode_ci,
  `created_at` int(11) DEFAULT NULL,
  `updated_at` int(11) DEFAULT NULL,
  PRIMARY KEY (`name`),
  KEY `rule_name` (`rule_name`),
  KEY `idx-auth_item-type` (`type`),
  CONSTRAINT `auth_item_ibfk_1` FOREIGN KEY (`rule_name`) REFERENCES `auth_rule` (`name`) ON DELETE SET NULL ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

CREATE TABLE `auth_rule` (
  `name` varchar(64) COLLATE utf8_unicode_ci NOT NULL,
  `data` text COLLATE utf8_unicode_ci,
  `created_at` int(11) DEFAULT NULL,
  `updated_at` int(11) DEFAULT NULL,
  PRIMARY KEY (`name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

CREATE TABLE `auth_item_child` (
  `parent` varchar(64) COLLATE utf8_unicode_ci NOT NULL,
  `child` varchar(64) COLLATE utf8_unicode_ci NOT NULL,
  PRIMARY KEY (`parent`,`child`),
  KEY `child` (`child`),
  CONSTRAINT `auth_item_child_ibfk_1` FOREIGN KEY (`parent`) REFERENCES `auth_item` (`name`) ON DELETE CASCADE ON UPDATE CASCADE,
  CONSTRAINT `auth_item_child_ibfk_2` FOREIGN KEY (`child`) REFERENCES `auth_item` (`name`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

CREATE TABLE `auth_assignment` (
  `item_name` varchar(64) COLLATE utf8_unicode_ci NOT NULL,
  `user_id` varchar(64) COLLATE utf8_unicode_ci NOT NULL,
  `created_at` int(11) DEFAULT NULL,
  PRIMARY KEY (`item_name`,`user_id`),
  CONSTRAINT `auth_assignment_ibfk_1` FOREIGN KEY (`item_name`) REFERENCES `auth_item` (`name`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;`

添加的时候会出错
输入图片说明
输入图片说明

  • 回答于 2015-01-21 11:11 举报

    在create某个权限或角色之前,最好判断一下要添加的项目是否已经存在,你的报错应该是这个问题引起的

  • 回答于 2015-04-27 12:54 举报

    actionCreateItemChild()方法中的if(empty($data['parent'])...)应该换成isset($data['parent'])吧。。

  • 回答于 2018-09-13 12:51 举报

    我也碰到了这个问题,权限和角色都在,但是一绑定就报错

  • 回答于 2018-12-05 14:03 举报

    请问你已经解决了么,能分享一下么

您需要登录后才可以回答。登录 | 立即注册
changepll
职场新人

changepll

注册时间:2014-05-14
最后登录:2016-05-10
在线时长:5小时23分
  • 粉丝2
  • 金钱5
  • 威望0
  • 积分55

热门问题