实体公共字段的学说继承 [英] Doctrine inheritance for entities common fields

查看:142
本文介绍了实体公共字段的学说继承的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在Web项目中使用Zend Framework 3和Doctrine ORM.

I'm using Zend Framework 3 and Doctrine ORM for my web project.

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

I have several modules in my application (User, Stock, Sales) and some entity models on each Module:

  • User模块实体:UserAccount等.
  • Stock模块实体:SKUStockLevel等.
  • Sales模块实体:InvoicePaymentMethod等.
  • User module entities: User, Account, etc..
  • Stock module entities: SKU, StockLevel, etc..
  • Sales module entities: Invoice, PaymentMethod, etc..

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

By default all entities has common fields, things like:

  • creationDateTime:创建日期/时间
  • creationUser:创建实体的用户
  • lastChangeDateTime:上次实体更改的日期/时间
  • lastChangeUser:上次更改实体的用户
  • creationDateTime: Date/time of creation
  • creationUser: User who create the entity
  • lastChangeDateTime: Date/time of last entity change
  • lastChangeUser: User who last changed the entity

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

I don't want to put those fields or every entity, but rather create a project base class that will extend all of my entities. I need to have common methods that will work on all entities, ie:

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

我可以看到来自文档,它表明我需要使用单表继承,但是我不知道具体如何做.问题:

As I can see from the documentation, it seens that I need to use the single table inheritance, but I can't figure out exactly how. Questions:

a),Doctrine将使用单表继承在数据库中为这些字段创建基表,或者将每个实体表的基字段和实体字段连接在一起,换句话说,我将仅具有实体表还是该继承关系还将为基本字段创建数据库表?

a) By using single table inheritance, will Doctrine create a base table in database for these fields or will join the base and the entity fields for every entity table, or in other words, will I have just the entity table or this inheritance will create a database table for the base fields also ?

b)我应该在哪里放置基本实体,以便可以将其继承给不同模块上的所有实体?

b) Where should I put my base entity so that it can be inherited for all entities on different module ?

我将不胜感激,有人可以举一些例子/链接来说明如何做到这一点.

I would appreciate it someone could put some example/links on how to do it.

推荐答案

单表继承并不是您所需要的.

For what you want to do single table inheritance is not what you need.

有2个选项:

您进行MappedSuperClass(可在

You make a MappedSuperClass (documentation can be found in chapter 6.1: Mapped Superclasses) and you add those common fields in that base class. Then you extend all the classes that need those fields from your base (mapped super) 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)您使用特质

您创建一个特征(或每个字段/关联几个独立的特征),并在需要具有这些公共字段的所有类中使用.

2) You use a Trait

You make a trait (or several separate traits for each field/association) that you use inside all the classes which need to have those common fields.

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)在文档中,您可以阅读:

Answers to your questions:

a) In the docs you can read:

单表继承是一种继承映射策略,其中层次结构的所有类都映射到单个数据库表.为了区分哪一行代表层次结构中的哪种类型,使用了所谓的鉴别符"列.

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.

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

It would mean that all those entities would share a common table, this absolutely not what you want. It will probably become a huge table (a row for each entity) slowing down your queries. On top of this there will also be columns in the table for all not commonly shared fields and those columns would be empty (null) for the entities that don't have those fields. It also means those not shared fields cannot have a null constraint. Again straight from the documentation:

要使单表继承在使用旧数据库模式或自写数据库模式的方案中工作,必须确保所有不在根实体中但在任何其他不同列中的列子实体必须允许使用空值.具有NOT 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.

此类继承仅对于与巨大扩展相似的实体是必需的,并且不适用于您在问题中谈论的示例.

Such inheritance is only necessary for entities that are similar to a huge extend and is not suitable for the examples you are talking about in your question.

b)您只需在通用模型(例如Application文件夹)中添加基本实体(即MappedSuperClass).

b) You can just add the base entity (so the MappedSuperClass) in a common model (like your Application folder).

这篇关于实体公共字段的学说继承的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆