建模引用不同实体的用户帐户

时间:2017-04-01 14:14:20

标签: php symfony domain-driven-design user-management clean-architecture

我正在启动一个新项目,它将作为授权/身份验证服务器,并为特定类型的用户提供简单的用户管理。用户可以是HelpDeskResponsibleGroupManagerEmployeeCustomer等。所有这些组成员都可以在Web界面上使用相同的表单登录。每个模型都包含描述它们的不同数据集。

我的问题是模型设计。我很确定我需要一些User实体,其中包含登录和读取角色所需的所有数据,但我不知道如何将其余模型与用户帐户相关联以轻松获取有关已登录用户的信息。另一个问题是用户管理 - 如果创建了用户帐户,我需要以某种方式将其链接到我上面提到的类型之一的模型。

我的概念是否过度工程化?有这样的问题的解决方案吗?也许我不需要针对不同帐户类型的多个实体?

感谢您的任何建议。

编辑:不同的权限级别不是这里的最大问题 - 我想根据用户所属的角色存储有关用户的不同信息。 Customer将拥有与Employee不同的数据集。我很确定它们是不同的型号,但我想保存使用相同登录表单登录的功能。

2 个答案:

答案 0 :(得分:2)

我认为主要的问题是你的耦合是倒退的:在你的情况下,用户管理上下文必须知道其他有界上下文(BC)的细节,而它应该是另一种方式。否则,您将发现自己不得不经常修改用户管理上下文,因为更多系统正在使用它。

例如,HelpDeskResponsible角色很可能在帮助台系统中播放,该系统位于其自己的BC(或一组BC)中。正是这个上下文应该负责建模和持久化HelpDeskResponsible的细节。用户管理上下文应该保留的唯一内容是用户是否处于特定角色,并且可能是某些通用于所有用户的信息(例如,名字,姓氏)。

enter image description here

显然,上图忽略了反腐败层(服务,例如HelpDeskUserService),它位于帮助台BC中,负责抽象出与用户管理BC的耦合并翻译{{ 1}}进入User

答案 1 :(得分:0)

由于您的其他实体会将User实体扩展为其他附加数据,因此我可能会使用Class Table Inheritance

  

类表继承是一种继承映射策略,其中每个都是   层次结构中的类映射到多个表:它自己的表和   所有父类的表。子类的表是链接的   通过外键约束到父类的表。   学说2通过使用鉴别器来实现这一策略   层次结构最顶层表中的列,因为这是   使用类表实现多态查询的最简单方法   继承。

这样,您将拥有一个基表User,其中包含基本数据(用户名,密码,电子邮件等),然后是每个附加实体的另一个表,其中包含附加数据User(例如表salary上的Employee列。

定义父实体

在这里,我们告诉Doctrine User是我们的基类。然后,Doctrine使用鉴别器列来标识您的用户所属的实体。当然,您需要映射要从User扩展的所有实体(此处我只添加Employee)。

/**
 * @ORM\Entity(repositoryClass="AppBundle\Repository\UserRepository")
 * @ORM\Table(name="user")
 * @ORM\InheritanceType("JOINED")
 * @ORM\DiscriminatorColumn(name="discr", type="string")
 * @ORM\DiscriminatorMap({"user" = "User", "employee" = "Employee"})
 */
class User {
    // your class..
}

定义子实体

/**
 * @ORM\Entity(repositoryClass="AppBundle\Repository\EmployeeRepository")
 * @ORM\Table(name="employee")
 */
class Employee extends User {

    /**
     * @ORM\Column(name="salary", type="float")
     */
    private $salary;

    public function setSalary($salary)
    {
        $this->salary = $salary;
        return $this;
    }

    public function getSalary()
    {
        return $this->salary;
    }

}

当然Employee类可以覆盖父方法(例如getRoles()如果您将UserInterface实现为User)。

最后(备份您的数据库)并使用php bin/console doctrine:schema:update --force更新您的数据库架构。 Doctrine将创建包含已定义数据的新表以及引用相对id的列User

因此,当普通用户登录时,Symfony将加载User实体,而当员工登录时,它将加载Employee实体。