我正在为我的 Web 项目使用 Zend Framework 3 和 Doctrine ORM。
我的应用程序中有几个模块(User
、Stock
、Sales
)和每个模块上的一些实体模型:
User
模块实体:User
, Account
等。Stock
模块实体:SKU
, StockLevel
等。Sales
模块实体:Invoice
, PaymentMethod
等。默认情况下,所有实体都有公共(public)字段,例如:
creationDateTime
: 创建日期/时间creationUser
: 创建实体的用户lastChangeDateTime
: 上次实体更改的日期/时间 lastChangeUser
: 上次更改实体的用户 我不想放置这些字段或每个实体,而是创建一个项目基类来扩展我的所有实体。我需要有适用于所有实体的通用方法,即:
/**
* 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 ,它看到我需要使用单表继承,但我不知 Prop 体如何。问题:
一)通过使用单表继承,Doctrine 将在数据库中为这些字段创建一个基表,还是将每个实体表的基字段和实体字段连接起来,或者换句话说,我将只有实体表还是这个继承将创建一个数据库基字段的表也可以吗?
b) 我应该把我的基础实体放在哪里,以便它可以被不同模块上的所有实体继承?
我会很感激有人可以提供一些示例/链接来说明如何做到这一点。
最佳答案
对于您想要做的单表继承不是您所需要的。
有2个选项:
1)MappedSuperClass(几乎直接来自文档)
你做一个MappedSuperClass
(文档可以在章节 6.1: Mapped Superclasses 中找到)并且您在该基类中添加这些公共(public)字段。然后,您从基类(映射的父类(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)你使用一个特质
您制作了一个特征(或每个字段/关联的几个单独的特征),您在所有需要具有这些公共(public)字段的类中使用。
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
}
回答您的问题:
一)在文档中,您可以阅读:
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
约束。再次直接来自文档: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.
这种继承仅对类似于巨大扩展的实体是必需的,并且不适合您在问题中讨论的示例。
b) 您可以在通用模型(如您的
MappedSuperClass
文件夹)中添加基本实体(因此 Application
)。
关于php - 实体公共(public)字段的学说继承,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40847451/