【问题标题】:Symfony framework; idiomatic way to store a user's roleSymfony 框架;存储用户角色的惯用方式
【发布时间】:2012-03-23 21:54:36
【问题描述】:

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

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

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

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

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

    • 另外:计算成本不高
    • 缺点:很难让所有用户都拥有特定角色
    • 缺点:像这样的数据库字段让小猫哭泣(规范化和其他东西)
  3. 每个角色的用户实体中有 5 个二进制字段

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

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

【问题讨论】:

  • 如何修复子列表项周围的间距?
  • 选项 1 当然是安全的方法。如果您需要在您的角色(权限等)上挂起其他关系,那么您将全部设置好。选项 2 可能会工作得很好。也许使用带有位映射的整数来存储角色?稍微干净、可扩展和可查询。只是不要让小猫看到它。
  • 你不能用FOSUserBundle这个吗?
  • 你为什么不用Symfony Access Control Lists

标签: php symfony doctrine-orm authorization idioms


【解决方案1】:

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

选项 1:关系方式

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

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

关于您对角色永远不会改变的担忧:存储关系数据与它改变的频率无关。人们应该永远记住需求会发生变化。你现在以优化的名义搞得越多,当需要更多角色更频繁地变化时,你就越挣扎。

当然,您可能会遇到性能问题,尤其是当您遇到某种急切加载问题,或者您没有缓存内容并且必须在每次页面加载时重新加载角色时。但是,关系数据库旨在支持此类内容,因此这里应该有优化查询的方法。

选项 2:破解

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

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

选项 3:务实的解决方案

每个角色有 5 个布尔值的第三个选项在中间:没有办法搞砸它,性能应该不是问题。更新和删除角色或添加新角色一样简单。很清楚这些领域的作用,所以这方面也没有伤害。它使您的实体和数据库看起来更难看,并且您的用户模型中也会有角色名称,并将真/假字段映射到正确的角色名称,这可能有点令人困惑。

结果

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

如果您已经证明您的应用程序由于角色表而运行缓慢,您以后可以随时使用选项 3。您只需要更改您的用户实体并使用一个查询来提取角色并为每个用户设置正确的真/假组合。如果软件是干净的,这是几个小时的问题,所以现在不需要考虑性能可能不好。

【讨论】:

  • +1 很棒的答案。 FOSUserBundle 将角色存储在一个数组中。是否有可能对此发表您的专家意见?非常感谢@Sgoettschkes。
猜你喜欢
  • 2017-03-17
  • 1970-01-01
  • 2018-10-16
  • 1970-01-01
  • 2015-11-02
  • 2013-06-27
  • 2016-11-18
  • 2019-09-24
  • 1970-01-01
相关资源
最近更新 更多