本文主要全面讲解在不适用第三方包的情况下,如何在基于Laravel框架上,研发社交系统ThinkSNS+时,简历一套优雅而不失性价比的用户权限管理体系功能,【内含ThinkSNS真实代码】。

需求场景

就是用户组+权限节点,这个需求 laravel 有很多很好的第三方包实现。下面描述代码不参与缓存机制纯数据库查询,给大家提供一个思路。

下面的代码都是来自于ThinkSNS+,是基于 Laravel 全新开发的 ThinkSNS 社交开源项目,遵循 Apache-2.0 开源协议。欢迎 Star 哦。

数据表设计

其实这一块我个人是参考的 Zizaco/entrust 因为我觉得,大多数情况下,我们要用的角色和权限节点都是真多用户的。数据表设计如下:

可以看到关系如下 user -> role -> ability ,其中关系全部都是多对多关系。一个用户可以拥有多个 role,一个 ability 可以被分配给多个 role 。

链式方法设计

$user->ability('create user'); // 判断是否有 create user 权限。
$user->ability('owner', 'delete user'); // 判断用户是否拥有 owner 用户组,且是否这个组拥有 delete user 权限。
$user->ability(); // 返回一个 Ability 实例。
$user->roles; // 读取用户所拥有的所有用户组。
$user->roles(); // 获取 Builder 实例。
$user->roles('owner'); // 检查用户是否拥有 owner 用户组,拥有返回 model 实例,否则返回 false。
$user->ability()->roles(); // 读取用户所拥有的所有用户组。返回的是一个 集合。可用集合所有方法。
$user->ability()->roles('owner'); // 检查用户是否拥有 owner 用户组,拥有返回 model 实例,否则返回 false。
$user->ability()->all(); // 返回用户拥有的所有权限集合。
$user->ability()->all('create user'); // 检查用户是否拥有 create user 权限,没有返回 false ,有返回 ability 实例。
其中调用 $user->ability()->all() 和 $user->ability()->all() 都是返回的 集合 可以链式调用集合下的所有方法进一步操作。

ability 用户 Trait

<?php

namespace ZhiyiPlusModelsConcerns;

use ZhiyiPlusModelsRole;
use ZhiyiPlusServicesUserAbility;

trait UserHasAbility
{

/*** Abiliry service instance.** @var \Zhiyi\Plus\Services\UserAbility*/
protected $ability;/*** User ability.** @param array $parameters*        ability();*        ability($ability);*        ability($role, $ability);* @return mixed* @author Seven Du <shiweidu@outlook.com>*/
public function ability(...$parameters)
{if (isset($parameters[1])) {return ($role = $this->resolveAbility()->roels($parameters[0]))? $role->ability($parameters[1]): false;} elseif (isset($parameters[0])) {return $this->resolveAbility()->all($parameters[0]);}return $this->resolveAbility();
}/*** The user all roles.** @param string $role* @return mied* @author Seven Du <shiweidu@outlook.com>*/
public function roles(string $role = '')
{if ($role) {return $this->ability()->roles($role);}return $this->belongsToMany(Role::class, 'role_user', 'user_id', 'role_id');
}/*** Resolve ability service.** @return \Zhiyi\Plus\Services\UserAbility* @author Seven Du <shiweidu@outlook.com>*/
protected function resolveAbility()
{if (! ($this->ability instanceof UserAbility)) {$this->ability = new UserAbility();}return $this->ability->setUser($this);
}

}
Ability 实例

<?php
namespace ZhiyiPlusServices;
use IlluminateSupportCollection;
use ZhiyiPlusModelsUser as UserModel;
use ZhiyiPlusContractsModelUserAbility as UserAbilityContract;

class UserAbility implements UserAbilityContract
{

protected $user;/*** Get all roles or get first role.** @param string $role* @return mixed* @author Seven Du <shiweidu@outlook.com>*/
public function roles(string $role = '')
{$roles = $this->user()->roles()->get()->keyBy('name');if (! $role) {return $roles;}return $roles->get($role, false);
}
/*** Get all abilities or get first ability.** @param string $ability* @return mixed* @author Seven Du <shiweidu@outlook.com>*/
public function all(string $ability = '')
{$roles = $this->roles();$roles->load('abilities');$abilities = $roles->reduce(function ($collect, $role) {return $collect->merge($role->abilities->keyBy('name'));}, new Collection());if (! $ability) {return $abilities;}return $abilities->get($ability, false);
}
/*** Get user instance.** @return \Zhiyi\Plus\Models\User* @author Seven Du <shiweidu@outlook.com>*/
public function user(): UserModel
{return $this->user;
}
/*** Set user model.** @param \Zhiyi\Plus\Models\User $user* @author Seven Du <shiweidu@outlook.com>*/
public function setUser(UserModel $user)
{$this->user = $user;return $this;
}

}
Role 模型所需代码

<?php
namespace ZhiyiPlusModels;
use IlluminateDatabaseEloquentModel;

class Role extends Model
{

/*** Get all abilities of the role.** @return \Illuminate\Database\Eloquent\Relations\BelongsToMany* @author Seven Du <shiweidu@outlook.com>*/
public function abilities()
{return $this->belongsToMany(Ability::class, 'ability_role', 'role_id', 'ability_id');
}
/*** Get or check The role ability.** @param string $ability* @return false|\User\Plus\Models\Ability* @author Seven Du <shiweidu@outlook.com>*/
public function ability(string $ability)
{return $this->abilities->keyBy('name')->get($ability, false);
}

}
使用

然后我们打开 User 模型wen jia文件添加如下代码:

class User ...
{

use UserHasAbility;

}
总结

其实性状在 User 模型中只暴露了 roles 和 ability 两个公开方法。但是已经足以胜任用户组权限判断逻辑了。

整个 ability 都是结合在集合之上的一些封装,这样是的代码调用更加优雅。

以上代码是在开发ThinkSNS+中的实际真实代码。具体的实现可参考项目。

以上代码都来自于ThinkSNS Plus,看完整的开发代码可以看仓库:

GitHub: https://github.com/slimkit/thinksns-plus
(开源不易,求 Star )

ThinkSNS产品免费体验:http://www.thinksns.com/experience.html

不使用三方包时,如何在ThinkSNS中建立优雅的用户权限管理相关推荐

  1. django 传递中文_如何在Django中建立消息传递状态

    django 传递中文 by Ogundipe Samuel 由Ogundipe Samuel 如何在Django中建立消息传递状态 (How to Build a Message Delivery ...

  2. python中如何画logistic_如何在 Python 中建立和训练线性和 logistic 回归 ML 模型?

    原标题:如何在 Python 中建立和训练线性和 logistic 回归 ML 模型? 英语原文: 翻译:(Key.君思) 线性回归与logistic回归,是. 在我的里,你们已经学习了线性回归机器学 ...

  3. 如何在Python中建立和训练K最近邻和K-Means集群ML模型

    One of machine learning's most popular applications is in solving classification problems. 机器学习最流行的应 ...

  4. 如何在WordPress中建立电子邮件列表–电子邮件营销101

    Building an email list is a hot topic among bloggers and small business owners. Just about every exp ...

  5. 我如何在JavaScript中建立良好的发布过程

    by Dafna Rosenblum 达夫娜·罗森布拉姆(Dafna Rosenblum) 我如何在JavaScript中建立良好的发布过程 (How I established a good rel ...

  6. 智慧、智能图书馆管理平台系统+web端业务数据管理平台+Axure通用web端高保真交互业务数据管理平台+铭牌管理+设备监控+系统管理+内容管理+机构列表管理+用户权限管理+专题管理+服务包管理

    作品介绍:智慧.智能图书馆管理平台系统+web端业务数据管理平台+Axure通用web端高保真交互业务数据管理平台+铭牌管理+设备监控+系统管理+内容管理+机构列表管理+用户权限管理+专题管理+服务包 ...

  7. 如何在CCS中建立自己的工程

    如何在CCS中建立自己的工程 相信有很多人用了好久的CCS了,却不会建立自己的工程文件,大家要不就是在TI的例程里改,要不就是弄的工程文件路径很复杂,而且有时还会有致命的缺点--不能换路径,也就是说放 ...

  8. was服务器里面jar包_如何在was中解决jar包冲突

    如何在 was 中解决 jar 包冲突 大型的基于 WebSphere 的项目开发中,同一个 WebSphere Application Server (以下 简称 WAS ) 上会部署多个应用程序, ...

  9. python构造icmp数据包_如何在python中构造ICMP数据包

    为了学习,我目前正在尝试创建一个简单的python porgram来向某个设备发送ICMP ping数据包.为了开始,我查看了python模块Pyping:https://github.com/Akh ...

最新文章

  1. 马云再谈996,又一次被网友怒骂:马老师,求求你闭嘴吧!
  2. c语言 mysql_bind,linux C mysql的blob门类字段的插入和读取
  3. 实战项目三:爬取QQ群中的人员信息
  4. C语言 | 求级数的和
  5. 学习《送东阳马生序》
  6. Linux运维常用命令总结
  7. mysql 时间戳 2038_mysql数据库的timestamp为什么从1970到2038的某一时间?某一时间是指什么时间?过了这个时间之后怎么办?-问答-阿里云开发者社区-阿里云...
  8. 【知识笔记】WebForm
  9. 课题申报书范文_课题申请书范例
  10. 关于多元正态分布的条件概率密度
  11. 中年男人,你如何自我救赎
  12. 华为音频编辑服务实时变声,多种音色随意变换
  13. 利用正则表达式爬取豆瓣读书top250书籍信息 附有详细分析
  14. c语言设计程序实现顺序冒泡_C语言学习 顺序程序设计
  15. 安防视频监控系统方案 现代机场安防视频监控系统
  16. excel 批量生成条码
  17. 「Python条件结构」使用if结构实现密码验证
  18. 内存的分配与回收实验
  19. jquery 图片转为base64
  20. 如何优雅地使用Sublime

热门文章

  1. Java程序员从笨鸟到菜鸟之(八十六)跟我学jquery(二)大话jquery选择器
  2. 程序员面试题精选100题(54)-C++/C#面试题(3)
  3. Earth Mover's Distance (EMD)距离
  4. 主成分分析(Principal components analysis)-最大方差解释
  5. Machine Learning week 8 quiz: Principal Component Analysis
  6. Markdown 简明教程
  7. 2015年浪潮面试题
  8. 【OpenCV3】阈值化操作——cv::threshold()与cv::adaptiveThreshold()详解
  9. Java 文件及文件夹复制
  10. windows查看进程线程的命令pslist