Symfony框架;存储用户的惯用方式';的角色


Symfony framework; idiomatic way to store a user's role

在我的Symfony 2应用程序中,我想使用用户和角色的标准授权系统(http://symfony.com/doc/2.0/book/security.html)

我的用户是一个存储在数据库中的实体,带有条令(实现用户界面)。我的系统中将有5个预定义的角色,每个用户可能有多个这样的角色。

实现这一点最惯用的方法是什么?我正在考虑以下三种解决方案。

  1. 创建一个单独的角色实体,并与用户实体创建多对多关系

    • 另外:易于获得具有特定角色的所有用户
    • Con:资源密集型?(总是需要双重联接才能获取用户的所有角色)
    • Con:不是idomatic?角色(及其名称)的数量永远不会改变,那么将其作为一个单独的实体存储在数据库中有意义吗
  2. 在用户中有一个字段,它是一个排序的、逗号分隔的角色列表,getRoles()实现为explode(',',this.all_roles)

    • 另外:计算成本不高
    • 缺点:很难获得具有特定角色的所有用户
    • Con:像这样的数据库字段让小猫哭了(正常化之类的)
  3. 每个角色在用户实体中有5个二进制字段

    • 另外:计算成本不高
    • 另外:易于获得具有特定角色的所有用户
    • Con:感觉还是不太好

实现这个系统最常用的方法是什么?

当然,答案在很大程度上取决于您的需求,但我会尽可能在全球范围内回答。

选项1:关系方式

从纯关系的角度来看,您希望数据库规范化,这将导致您的第一个选择:一个与用户表具有m:n关系的角色表。这有一些优点:

  • 好吧,这是人们期望数据库工作的方式,所以没有隐藏在实体中的功能
  • 没有办法把事情搞砸(比如当你有一个varchar字段,并期望它有某种格式,比如昏迷分离)
  • 做事只有一种方法

关于角色永远不会改变的担忧:存储关系型数据并不是关于它改变的频率。人们应该永远记住需求的变化。你现在越是以优化的名义搞砸了,以后就越需要更多的角色,而这些角色的变化更频繁。

当然,您可能会遇到性能问题,尤其是当您遇到某种急于加载的问题,或者如果您不缓存内容,并且必须在每次页面加载时重新加载角色时。但是,关系数据库是为支持这些东西而设计的,所以这里应该有优化查询的方法。

选项2:破解

第二种选择,简单地将所有角色存储到varchar中,在性能方面会更好。只需加载一个文本字段,一些PHP处理就完成了。另一方面,您可能会遇到以下几个问题:

  • 您无法控制varchar字段,因此一个故障脚本可能会危及整个应用程序(这真的很糟糕,但取决于您的项目,如果您是唯一的开发人员,并且您知道自己在做什么,它可能会进展顺利)
  • 更新一个数据集要困难得多,因为您必须提取所有角色,更新有问题的角色,并存储回
  • 查询具有特定角色的所有用户要困难得多
  • 删除角色要困难得多

选项3:务实的解决方案

第三个选项(每个角色5个布尔值)位于中间:没有办法搞砸它,性能也不应该成为问题。更新和删除角色或添加新角色一样简单。田地的作用很清楚,所以这一边也没有害处。这会使您的实体和数据库看起来有点难看,而且您的用户模型中也会有角色名称来将true/false字段映射到正确的角色名称,这可能会有点令人困惑。

结果

考虑到这一切,我会选择选项1。人们可能会认为性能是一个问题,但除非我有证据证明这一点,否则我不会考虑这些事情。最后,当你真的遇到真正的性能问题时,你该怎么办?您可以添加一些额外的硬件,优化您的dbms,优化查询,或者使用具有更高性能的内置dbms(你好,Oracle!)。

如果您已经证明您的应用程序由于角色表的原因而速度较慢,那么您以后可以始终使用选项3。您只需要更改用户实体,并有一个查询来提取角色,并为每个用户设置正确的真/假组合。如果软件是干净的,这是一个小时的问题,所以现在没有必要因为性能可能不好而这么做。