两个不同子类扩展同一个实体实例时的教义继承策略

Posted

技术标签:

【中文标题】两个不同子类扩展同一个实体实例时的教义继承策略【英文标题】:Doctrine inheritance strategy when two different subclasses extend the same entity instance 【发布时间】:2016-05-18 17:54:46 【问题描述】:

我正在开发一个管理法庭口译服务的应用程序(使用 Doctrine 和 Zend Framework 2)。涉及的人很多,他们具有各种专业角色,因此有一个 Person 超类和子类。类层次在纵向上并不复杂——一代继承就足够了——但是横向方面给我带来了麻烦。

我认为 mapped superclasses 不适合我的情况。我也考虑过single-table inheritance,但这很快就会变得丑陋,因为子类有自己的实体关系,太多东西不能优雅地塞进一个表中。

这给我们留下了class table inheritance,这在大多数方面都非常合适,但是......我将有很多情况,子类 User(用于身份验证)和子类 Interpreter 将(或应该)指向父数据表中的同一行,因为它们代表现实中的同一个人。但是由于有鉴别器列,您必须选择一个或另一个,否则会创建两个不同的行来保存相同的数据——规范化警察应该会为您服务。

我认为用户或解释器实体可能必须简单地与 Person 实体建立一对一的关系,并以半手动方式处理。我认为另一种选择是将 User 折叠成 Person ——但这很丑,因为很多人不会进行身份验证,也不会拥有或不需要密码。 我看过 Doctrine inheritance, several entities extending the same super class 和 How to change and entity type in Doctrine2 CTI Inheritance(除其他外)没有人解决这个问题。

所以,我想知道是否有人有任何建议。谢谢。

【问题讨论】:

可能是个人喜好,但我会将 User 作为一个独立的类。它可能使用与其他表相同的基础表,但独立于身份验证。然后可以使用 get 方法将其链接到适当的 Person 对象。 @Matt S:当您说“可能使用与其他表相同的基础表”时,您是在暗示可能有多个实体类映射到同一个表上?聪明的!但我的问题是电子邮件字段,理所当然地是用户的一个属性,是(截至目前)我的个人实体的列/属性,因为每个人都有一封电子邮件。也许我没有关注...我可以使用 getter 从 User 获取 Person,显然,一种或另一种方式,但我不希望身份验证变得不必要地复杂——Doctrine 模块在这方面做得很好—— - 我猜你同意。 【参考方案1】:

听起来您正在管理大量关于 Persons 的数据,这些数据可以识别世界上的个人。由于系统中只有一部分人是Users,我认为对身份验证、审计日志记录、通知等的关注与Person 类层次结构的关注是分开的。

我建议从 Person 类层次结构中删除 User。也许将其重命名为Account,让它感觉不那么人性化。一个Account 可以有一个owner 属性,它是与Person 的关系。如果您想使用Person 的电子邮件地址作为身份验证的标识符,那很好。如果您稍后想添加 username,那将是 Account 的属性,因为它仅在该上下文中有意义。

【讨论】:

我喜欢。这很可能是前进的方向。我希望不要违反基本的规范化原则,即一个事实一次只能存在于一个地方——例如,“有一个人叫 John Somebody”——同时不要为了避免这样做而做出可怕的扭曲。或者,不要太可怕:-) 我会回去再玩一些,但谢谢,这可能会奏效。【参考方案2】:

不确定底层代码(不是 ZF 开发人员),但我认为您混淆了行为和数据。

要使身份验证正常工作,您实际上不需要继承。刚刚发现您在接口依赖项之上编写代码。

为了使用户能够进行身份验证(而普通人不能) - 使用继承,或者像@timdev 建议的那样,使用关系。在 symfony 世界里我最好写这样的东西

class User extends Person implement UserInterface 
  //... implementation


class Person 
  //...

之后,您可以确定,您拥有UserInterface,尤其是任何服务和身份验证。

如果您必须动态切换 User 实体的底层类(即您有 Author extends Person 并希望允许某些作者登录),我认为组合是唯一合适的解决方案。拆分逻辑,拆分实体,拆分数据。开心点。

【讨论】:

谢谢。我同意你的观点。我现在确信,对于我的用户来说,要走的路是组合而不是继承。

以上是关于两个不同子类扩展同一个实体实例时的教义继承策略的主要内容,如果未能解决你的问题,请参考以下文章

XML 中的教义类继承

Hibernate 继承和 HQL

三大特性之多态

继承表的外键名称

教义 2 - 具有附加属性和继承的关联表

C++可不可以让子类继承父类的静态成员后赋予它各自不同的值?