我有一个class Employee extends Person. 随着时间的推移,一个已经存在的Person可以成为Employee公司的一个。
我知道使用原始 SQL 更改鉴别器类型或使用晦涩的 PECL 扩展进行类型转换是一种不好的做法。
但是是否有一种设计模式可以管理这些复杂性?
是克隆所有属性和关系(Person 与其他实体有很多关系)来实现这一目标的唯一方法吗?我将如何克隆现有的人及其所有关系?
我有一个class Employee extends Person. 随着时间的推移,一个已经存在的Person可以成为Employee公司的一个。
我知道使用原始 SQL 更改鉴别器类型或使用晦涩的 PECL 扩展进行类型转换是一种不好的做法。
但是是否有一种设计模式可以管理这些复杂性?
是克隆所有属性和关系(Person 与其他实体有很多关系)来实现这一目标的唯一方法吗?我将如何克隆现有的人及其所有关系?
由于Person和Employee是两个不同的“事物”,因此您应该创建一个与 Person 实体具有一对一关系的 Employee 实体。这意味着 Employee 始终是 Person,但 Person 不一定是 Employee。
class Employee
{
/**
* @ORM\OneToOne(targetEntity="Acme\PersonBundle\Entity\Person", cascade={"persist"})
* @ORM\JoinColumn(referencedColumnName="id", nullable=true)
*/
protected $person;
}
这不仅允许您保留 Person 实体及其所有现有属性,避免克隆数据(这绝不是一个好主意),而且最重要的是分离了两种对象类型。
正如@Zeljko 提到的,您可以创建一个类型字段字段,但我相信我对数据进行规范化的方法要干净得多。如果您需要多种类型的员工,那么您可以创建一个 EmployeeType 表,然后在 Employee 实体中拥有一个 EmployeeType_ID。这种方法比使用常量更干净,后者往往会变得混乱且难以维护。
克隆数据是个坏主意。记住:如果你在复制一些东西,你就做错了:)
我认为最好的解决方案是根本不使用继承。只需在名为例如的 Person 实体中创建新列。type这将是一个常数。在该实体中,放置如下内容:
class Person
{
const TYPE_USER = 0 ;
const TYPE_EMPLOYEE = 1 ;
const TYPE_BIG_FAT_BOSS = 2 ;
...
/**
* @ORM\Column(type="integer")
*/
protected $type = self::TYPE_USER ;
这样您只需要更新type列并拥有更好的功能。