实体公共字段的原则继承
Doctrine inheritance for entities common fields
我正在为我的 Web 项目使用 Zend Framework 3 和 Doctrine ORM。
我的应用程序中有几个模块(User
、Stock
、Sales
)和每个模块上的一些实体模型:
User
模块实体:User
、Account
等..
Stock
模块实体:SKU
、StockLevel
等..
Sales
模块实体:Invoice
、PaymentMethod
等..
默认情况下,所有实体都有公共字段,例如:
creationDateTime
: Date/time 创作
creationUser
: 创建实体的用户
lastChangeDateTime
:Date/time 上次实体更改
lastChangeUser
: 上次更改实体的用户
我不想放置这些字段或每个实体,而是创建一个项目库 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
)。
我正在为我的 Web 项目使用 Zend Framework 3 和 Doctrine ORM。
我的应用程序中有几个模块(User
、Stock
、Sales
)和每个模块上的一些实体模型:
User
模块实体:User
、Account
等..Stock
模块实体:SKU
、StockLevel
等..Sales
模块实体:Invoice
、PaymentMethod
等..
默认情况下,所有实体都有公共字段,例如:
creationDateTime
: Date/time 创作creationUser
: 创建实体的用户lastChangeDateTime
:Date/time 上次实体更改lastChangeUser
: 上次更改实体的用户
我不想放置这些字段或每个实体,而是创建一个项目库 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
)。