rbac 提示Integrity constraint violation (#23000) [ 2.0 版本 ]
配置步骤:
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;`
添加的时候会出错
共 4 个回答
-
kaler_mosen 回答于 2015-04-27 12:54 举报
actionCreateItemChild()
方法中的if(empty($data['parent'])...)
应该换成isset($data['parent'])
吧。。 -
fan_090113 回答于 2018-12-05 14:03 举报
请问你已经解决了么,能分享一下么
changepll
注册时间:2014-05-14
最后登录:2016-05-10
在线时长:5小时23分
最后登录:2016-05-10
在线时长:5小时23分
- 粉丝2
- 金钱5
- 威望0
- 积分55