原则2:使用联接表中的字段作为映射实体的标识符

时间:2019-05-03 17:40:24

标签: symfony doctrine-orm doctrine

在《 Doctrine 2 ORM》中,我有一个抽象的“通信”实体,该实体使用SINGLE_TABLE继承来确定它是哪种通信类型:

Communication.orm.yaml:

App\Entity\Communication:

    type: entity
    table: communication

    inheritanceType: SINGLE_TABLE
    discriminatorColumn:
        name: mode
        type: string
    discriminatorMap:
        push: App\Entity\Communication\Push
        notice: App\Entity\Communication\Notice
        email: App\Entity\Communication\Email

# ...

因此,有3种通信类型(推送,通知和电子邮件)都使用“通信”表。

每个“通讯”都是可翻译的。以前,我有3个实体包含这些翻译。这些i18n实体中的每个实体都使用相同的“ i18n_communication”表,并且与它们各自的通信类型包含双向多对一关系:

  • App \ Entity \ I18n \ Communication \ Push
  • App \ Entity \ I18n \ Communication \ Notice
  • App \ Entity \ I18n \ Communication \ Email

由于在Doctrine 2中具有多个使用同一表但没有表继承的实体是非法的,所以我使所有的I18n实体都扩展了一个基本的I18nCommunication类,类似于它们转换的非i18n实体:

I18nCommunication.orm.yaml:

App\Entity\I18N\Communication\I18nCommunication:

    type: entity
    table: i18n_communication
    inheritanceType: SINGLE_TABLE
    discriminatorColumn:
        name: communication.mode    ******
        type: string
    discriminatorMap:
        push: App\Entity\I18N\Communication\Push
        notice: App\Entity\I18N\Communication\Notice
        email: App\Entity\I18N\Communication\Email
# ...

这不起作用。所有扩展I18nCommunication的实体都有一个“通讯”字段,该字段引用了它们转换的通讯实体,但是Doctrine不知道该如何处理“名称:communication.mode”行。

我的问题是:如何使用相关实体中的字段作为区分列?

我尝试使用继承类型:JOINED并从Communication扩展了I18nCommunication,因此我可以访问父级的mode字段。但是,由于Communication的继承类型为SINGLE_TABLE,所以该方法不起作用,它认为I18nCommunication应该位于通讯表中。

有没有办法做到这一点?还是我不得不将我的I18nCommunication实体合并为一个实体?

谢谢。

1 个答案:

答案 0 :(得分:0)

这行不通。 DiscriminatorColumn在当前配置的Entity中声明。注释也是,它是“ EntityAnnotation”,而不是“ PropertyAnnotation”。

任何没有以下原因的原因:

class I18nCommunication { ... }
class Push extends I18nCommunication { ... }
class Notice extends I18nCommunication { ... }
class Email extends I18nCommunication { ... }
App\Entity\I18N\Communication\I18nCommunication:

    type: entity
    table: i18n_communication
    inheritanceType: SINGLE_TABLE
    discriminatorColumn:
        name: discr
        type: string

在使用Single Table Inheritance时,所有数据仍然存在。

接下来,不要声明DiscriminatorMap,Doctrine将自动为您处理。请参见上方STI链接下的最后一个项目符号:

  

如果未提供区分图,则该图将自动生成。自动生成的鉴别符将每个类的小写缩写名映射为键。

还要在问题标题中提问:

  

使用联接表中的字段作为区分符

这永远不会发生,很简单,因为:联接表将是唯一知道该数据的表。兄弟姐妹将无法使用它,因此他们永远都不知道自己是其他事物的一部分。

因此,也永远不会将其构建为可用的东西。

作为类别注释的鉴别符必须始终出现在被鉴别批次的“父”上。您的情况是:I18nCommunication。