实体公共字段的原则继承

Doctrine inheritance for entities common fields

我正在为我的 Web 项目使用 Zend Framework 3 和 Doctrine ORM。

我的应用程序中有几个模块(UserStockSales)和每个模块上的一些实体模型:

默认情况下,所有实体都有公共字段,例如:

我不想放置这些字段或每个实体,而是创建一个项目库 class 来扩展我的所有实体。我需要有适用于所有实体的通用方法,即:

  /**
   * Update the last change fields
   * @param string $user User that is updating 
   */
  public void updateLastChange($user)
  {
      $this->lastChageDataTime = \Datetime();
      $this->lastChangeUser = $user;
  }

如我所见from the documentation,它表明我需要使用单个 table 继承,但我不知道具体如何。问题:

a) 通过使用单个 table 继承,Doctrine 会在数据库中为这些字段创建一个基 table 还是将连接基和实体每个实体 table 的字段,或者换句话说,我将只有实体 table 还是此继承将为基字段创建一个数据库 table?

b) 我应该把我的基础实体放在哪里,以便不同模块上的所有实体都可以继承它?

如果有人可以提供一些 example/links 如何做到这一点,我将不胜感激。

对于你想做的事情,单一 table 继承不是你需要的。

有2个选项:

1) MappedSuperClass(几乎直接来自文档)

你制作了一个 MappedSuperClass(文档可以在 6.1: Mapped Superclasses 章中找到)并在该基础 class 中添加那些公共字段.然后你扩展所有需要你的基础字段的classes(映射的超级)class.

/** 
 * @MappedSuperclass 
 */
class MappedSuperclassBase
{
    /** @Column(type="datetime") */
    protected $creationDateTime;

    /** 
     * @ManyToOne(targetEntity="Application\Entity\User") 
     * @JoinColumn(name="created_by", referencedColumnName="id")
     */
    protected $creationUser;

    /** @Column(type="datetime") */
    protected $lastChangeDateTime;

    /** 
     * @ManyToOne(targetEntity="Application\Entity\User") 
     * @JoinColumn(name="updated_by", referencedColumnName="id")
     */
    protected $lastChangeUser;

    // ... more fields and methods
}

/** 
 * @Entity 
 */
class EntitySubClass extends MappedSuperclassBase
{
    /** @Id @Column(type="integer") */
    private $id;

    // ... more fields and methods
}

2) 你使用了一个特质

您创建了一个特征(或每个 field/association 的多个单独特征),您在所有需要具有这些公共字段的 classes 中使用。

trait BaseTrait
{
    /** @Column(type="datetime") */
    protected $creationDateTime;

    /** 
     * @ManyToOne(targetEntity="Application\Entity\User") 
     * @JoinColumn(name="created_by", referencedColumnName="id")
     */
    protected $creationUser;

    /** @Column(type="datetime") */
    protected $lastChangeDateTime;

    /** 
     * @ManyToOne(targetEntity="Application\Entity\User") 
     * @JoinColumn(name="updated_by", referencedColumnName="id")
     */
    protected $lastChangeUser ;

    // ... more fields and methods
}

/** 
 * @Entity 
 */
class EntitySubClass
{
    use BaseTrait;

    /** @Id @Column(type="integer") */
    private $id;

    // ... more fields and methods
}

您问题的答案:

a) 在文档中您可以阅读:

Single Table Inheritance is an inheritance mapping strategy where all classes of a hierarchy are mapped to a single database table. In order to distinguish which row represents which type in the hierarchy a so-called discriminator column is used.

这意味着所有这些实体将共享一个公共 table,这绝对不是您想要的。它可能会变成一个巨大的 table(每个实体一行),从而减慢您的查询速度。最重要的是,所有不常用共享字段的table列中也将有列,对于不存在的实体,这些列将为空(null) '有那些字段。这也意味着那些非共享字段不能有 null 约束。再次直接来自文档:

For Single-Table-Inheritance to work in scenarios where you are using either a legacy database schema or a self-written database schema you have to make sure that all columns that are not in the root entity but in any of the different sub-entities has to allows null values. Columns that have NOT NULL constraints have to be on the root entity of the single-table inheritance hierarchy.

这种继承仅对于类似于巨大扩展的实体是必需的,而不适合table您在问题中谈论的示例。

b) 您可以在通用模型(例如您的 Application 文件夹)中添加基本实体(因此 MappedSuperClass)。