一、用户角色
用户与角色之间的关系是多对多:
- 一个用户可以有多个角色;
- 一个角色可以被分配给多个角色。
二、前期准备
(一)路由
// 查看用户角色
Route::get('userroles/:id','UserAccess/read');
// 分配角色给用户
Route::post('userroles','UserAccess/save');
// 删除用户的角色
Route::post('userrole/delete','UserAccess/delete');
(二)控制器
使用命令
php think make:controller UserAccess
(三)表
1. 用户表
创建用户表的 SQL 语句:
CREATE TABLE `think_users` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '用户编号',
`name` varchar(255) NOT NULL,
`created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4;
用户表如下:
2. 角色表
创建角色表的 SQL 语句:
CREATE TABLE `think_role` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '编号',
`name` varchar(255) DEFAULT NULL COMMENT '角色名称',
`remark` varchar(255) DEFAULT NULL COMMENT '备注',
`del_flag` tinyint(4) DEFAULT '0' COMMENT '0 表示正常,-1表示被删除',
`created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=6 DEFAULT CHARSET=utf8mb4;
角色表如下:
3. 用户角色表(中间表)
创建用户角色表的 SQL 语句:
CREATE TABLE `think_user_role` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '编号',
`user_id` int(11) NOT NULL COMMENT '用户ID',
`role_id` int(11) NOT NULL COMMENT '角色ID',
`create_by` varchar(255) DEFAULT NULL COMMENT '创建人',
`created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=27 DEFAULT CHARSET=utf8mb4;
用户角色表如下:
(四)模型
1. 用户模型
使用命令:
php think make:model User
在用户模型中定义 roles
方法:
<?php
declare (strict_types = 1);
namespace app\model;
use think\Model;
class User extends Model
{
protected $name = 'think_users';
public function roles(){
return $this->belongsToMany(Role::class,'think_user_role','role_id','user_id');
}
}
2. 角色模型
php think make:model Role
在角色模型中定义 users
方法:
<?php
declare (strict_types = 1);
namespace app\model;
use think\Model;
class Role extends Model
{
protected $name = 'think_role';
public function users(){
return $this->belongsToMany(User::class,'think_user_role','user_id','role_id');
}
}
3. 用户角色模型
php think make:model Access
用户角色模型:
<?php
declare (strict_types = 1);
namespace app\model;
use think\Model;
use think\model\Pivot;
class Access extends Pivot
{
protected $name = "think_user_role";
protected $autoWriteTimestamp = true;
}
注意:中间表模型类必须继承 think\model\Pivot
。
三、修改控制器
<?php
declare (strict_types = 1);
namespace app\controller;
use think\Request;
use app\model\User;
class UserAccess
{
/**
* 分配角色给用户
*
* @param \think\Request $request
* @return \think\Response
*/
public function save(Request $request)
{
$params = $request->param();
$user_id = $params['user_id'];
$role_id = $params['role_id'];
$user = User::find($user_id);
$roles = $user->roles;
$role_ids = $this->collectionColumn($roles,'role_id');
if($this->isAssignRole($role_id,$role_ids)){
return $this->setJsonResult('error',40000,'已分配该角色,无需再次分配');
}
if(isset($params['create_by']) && !empty($params['create_by'])){
// 传入中间表的额外属性
$user->roles()->attach($role_id,['create_by'=>$params['create_by']]);
}else{
$user->roles()->attach($role_id);
}
return $this->setJsonResult('success',10000,'用户授权成功',['user_id'=>$user_id,'role_id'=>$role_id]);
}
/**
* 显示用户的角色
*
* @param int $id
* @return \think\Response
*/
public function read($id)
{
$user = User::find($id);
$roles = $user->roles;
// dump($roles);
$role_name = [];
foreach($roles as $role){
$role_name[] = $role->name;
}
return $this->setJsonResult('success',10000,'操作成功',$role_name);
}
/**
* 删除用户的角色
*
* @param int $id
* @return \think\Response
*/
public function delete(Request $request)
{
$params = $request->param();
$user_id = $params['user_id'];
$user = User::find($user_id);
$role_id = $params['role_id'];
$user->roles()->detach($role_id);
return $this->setJsonResult('success',10000,'删除用户权限成功');
}
public function setJsonResult($status,$code,$message='',$data=[]){
return json([
'status' => $status,
'code' => $code,
'message' => $message,
'data' => $data
]);
}
/**
* 获取数据集合某个字段的值
*
* @param object $collection, string $column
* @return array
*/
public function collectionColumn($collection,$column){
$re = [];
foreach($collection as $val){
$re[] = $val->pivot->$column;
}
return $re;
}
/**
* 判断之前是否为该用户分配过 role_id 对应的角色
*
* @param string $collection, array $role_ids
* @return bool
*/
public function isAssignRole($role_id,$role_ids){
if(in_array($role_id,$role_ids)){
return true;
}
return false;
}
}
四、测试
在之前的测试中已经为 id
为 1 的用户分配了角色,现在测试 2 号的用户角色的查看、分配与删除:
1. 查看 2 号用户的角色
调用查看用户角色的接口:
返回值的 data
属性为空。
2. 为用户分配角色
调用为用户分配角色的接口:
用户角色表如下:
再次调用查看用户角色的接口:
3. 删除用户的角色
调用删除用户角色的接口:
删除2号角色后的数据表:
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。