引用不同实体的建模用户帐户
Modeling user account referring to different entities
我正在开始一个新项目,该项目将作为 authorization/authentication 服务器和针对特定类型用户的简单用户管理。用户可以是 HelpDeskResponsible
、GroupManager
、Employee
、Customer
等。所有这些组成员将能够在 Web 界面上使用相同的表单登录。每个模型将包含描述它们的不同数据集。
我的问题是模型设计。我很确定我需要一些 User
实体,其中包含登录和读取角色所需的所有数据,但我不知道如何将其余模型与用户帐户相关联以轻松获取有关登录用户的信息。另一个问题是用户管理 - 如果创建了用户帐户,我需要以某种方式 link 它成为我上面提到的一种类型的模型。
我的概念是不是过度工程化了?有解决此类问题的方法吗?也许我不需要针对不同帐户类型的多个实体?
感谢任何建议。
编辑:不同的权限级别不是这里最大的问题——我想根据用户所属的角色存储不同的用户信息。 Customer
将具有与 Employee
不同的数据集。我很确定它们是不同的型号,但我想保留使用相同登录表单登录的功能。
我认为主要问题是你的耦合倒退了:在你的情况下,用户管理上下文必须了解其他限界上下文 (BC) 的细节,而它应该是相反的。否则,您会发现自己必须不断修改您的用户管理上下文,因为越来越多的系统正在使用它。
例如,HelpDeskResponsible
角色很可能在位于自己的 BC(或一组 BC)中的帮助台系统中扮演。正是那个上下文应该负责建模和持久化 HelpDeskResponsible
的细节。用户管理上下文唯一应该包含的是用户是否处于特定角色以及可能对所有用户通用的一些信息(例如名字,姓氏)。
显然,上图遗漏了位于帮助台 BC 中的反腐败层(服务,例如 HelpDeskUserService
),它负责抽象出与用户管理 BC 的耦合并翻译User
变成 HelpDeskResponsible
.
由于您的附加实体使用其他附加数据扩展 User
实体,我可能会使用 Class Table Inheritance.
Class Table Inheritance is an inheritance mapping strategy where each
class in a hierarchy is mapped to several tables: its own table and
the tables of all parent classes. The table of a child class is linked
to the table of a parent class through a foreign key constraint.
Doctrine 2 implements this strategy through the use of a discriminator
column in the topmost table of the hierarchy because this is the
easiest way to achieve polymorphic queries with Class Table
Inheritance.
这样,您将有一个包含基本数据(用户名、密码、电子邮件等)的基本 table User
,然后每个附加实体都有另一个 table User
带有附加数据(例如 table Employee
上的第 salary
列)。
定义父实体
这里我们告诉 Doctrine User
是我们的基础 class。然后 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
class 可以覆盖父方法(例如 getRoles()
如果您将 UserInterface
实现到 User
)。
最后(备份您的数据库并)使用 php bin/console doctrine:schema:update --force
更新您的数据库架构。 Doctrine 将创建新的 table,其中包含已定义的数据以及引用相对 User
.
的列 id
因此,当普通用户登录时,Symfony 将加载 User
个实体,而当员工登录时,它将加载 Employee
个实体。
我正在开始一个新项目,该项目将作为 authorization/authentication 服务器和针对特定类型用户的简单用户管理。用户可以是 HelpDeskResponsible
、GroupManager
、Employee
、Customer
等。所有这些组成员将能够在 Web 界面上使用相同的表单登录。每个模型将包含描述它们的不同数据集。
我的问题是模型设计。我很确定我需要一些 User
实体,其中包含登录和读取角色所需的所有数据,但我不知道如何将其余模型与用户帐户相关联以轻松获取有关登录用户的信息。另一个问题是用户管理 - 如果创建了用户帐户,我需要以某种方式 link 它成为我上面提到的一种类型的模型。
我的概念是不是过度工程化了?有解决此类问题的方法吗?也许我不需要针对不同帐户类型的多个实体?
感谢任何建议。
编辑:不同的权限级别不是这里最大的问题——我想根据用户所属的角色存储不同的用户信息。 Customer
将具有与 Employee
不同的数据集。我很确定它们是不同的型号,但我想保留使用相同登录表单登录的功能。
我认为主要问题是你的耦合倒退了:在你的情况下,用户管理上下文必须了解其他限界上下文 (BC) 的细节,而它应该是相反的。否则,您会发现自己必须不断修改您的用户管理上下文,因为越来越多的系统正在使用它。
例如,HelpDeskResponsible
角色很可能在位于自己的 BC(或一组 BC)中的帮助台系统中扮演。正是那个上下文应该负责建模和持久化 HelpDeskResponsible
的细节。用户管理上下文唯一应该包含的是用户是否处于特定角色以及可能对所有用户通用的一些信息(例如名字,姓氏)。
显然,上图遗漏了位于帮助台 BC 中的反腐败层(服务,例如 HelpDeskUserService
),它负责抽象出与用户管理 BC 的耦合并翻译User
变成 HelpDeskResponsible
.
由于您的附加实体使用其他附加数据扩展 User
实体,我可能会使用 Class Table Inheritance.
Class Table Inheritance is an inheritance mapping strategy where each class in a hierarchy is mapped to several tables: its own table and the tables of all parent classes. The table of a child class is linked to the table of a parent class through a foreign key constraint. Doctrine 2 implements this strategy through the use of a discriminator column in the topmost table of the hierarchy because this is the easiest way to achieve polymorphic queries with Class Table Inheritance.
这样,您将有一个包含基本数据(用户名、密码、电子邮件等)的基本 table User
,然后每个附加实体都有另一个 table User
带有附加数据(例如 table Employee
上的第 salary
列)。
定义父实体
这里我们告诉 Doctrine User
是我们的基础 class。然后 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
class 可以覆盖父方法(例如 getRoles()
如果您将 UserInterface
实现到 User
)。
最后(备份您的数据库并)使用 php bin/console doctrine:schema:update --force
更新您的数据库架构。 Doctrine 将创建新的 table,其中包含已定义的数据以及引用相对 User
.
id
因此,当普通用户登录时,Symfony 将加载 User
个实体,而当员工登录时,它将加载 Employee
个实体。