是否可以(并推荐)为一张桌子使用多个模型?
我有多种类型的“人”(老师、学生、员工、公司),并希望将它们存储在同一张表中。他们拥有所有共同的个人数据,但有其他关系(例如学生 -> 公司、教师 -> 房间等)、附加信息(例如公司:公司名称、教师:教育)等等。
为这种情况获得一些最佳实践会很好。
是否可以(并推荐)为一张桌子使用多个模型?
我有多种类型的“人”(老师、学生、员工、公司),并希望将它们存储在同一张表中。他们拥有所有共同的个人数据,但有其他关系(例如学生 -> 公司、教师 -> 房间等)、附加信息(例如公司:公司名称、教师:教育)等等。
为这种情况获得一些最佳实践会很好。
这真的很简单!您必须制作这样的实体:
/**
* @ORM\Entity
* @ORM\InheritanceType("JOINED")
* @ORM\DiscriminatorColumn(name="discr", type="string")
* @ORM\DiscriminatorMap({"teacher" = "Teacher"})
*/
class Person
{
/**
* @ORM/Id
**/
private $id;
/**
* @ORM/Column
**/
private $name;
//setters getters and all the stuff
}
在 Teacher.php 文件中:
/**
* @ORM\Table()
* @ORM\Entity()
*/
class Teacher extends Person
{
private $salary;
}
成功的关键是这两个注释:
@ORM\DiscriminatorColumn(name="discr", type="string")
@ORM\DiscriminatorMap({"teacher" = "Teacher"})
首先是告诉 ORM 将使用哪一列来验证人员是否是教师。其次是告诉哪些类正在扩展基本 Person 类以及在我之前提到的列中放入什么。当您这样做时,您将有两个表,但在教师中,您将只有添加到教师实体的数据:)
一般来说,在使用 ORM 时,您必须考虑对象抽象级别并且不关心 DB(嗯,这并不完全正确,但这是一般的想法):)
不建议这样做。以下是我能想到为什么不这样做的几个原因:
IBM 有一篇关于在关系数据库中映射继承的好文章,在实现这种类型的模型时,我已经多次提到它。他们引用了三种方法:(1)使用单个表来表示所有类(您提出的方法),(2)对子类使用单独的表,或(3)对所有类使用单独的表。最后,它归结为个人喜好,但我通常这样做的方式是#2和#3之间的混合,我为所有类创建模型,但我限制了子类对父类的访问,而是编写快捷方法来访问父数据。考虑一下:
class Person
{
private $id;
private $name;
public function getId()
{ return $this->id; }
public function getName()
{ return $this->name; }
public function setName($name)
{ return $this->name; }
}
class Teacher
{
private $id;
private $person; // reference to Person table
private $salary;
public function getId()
{ return $this->id; }
private function getPerson()
{ return $this->person; }
public function getSalary()
{ return $this->salary; }
public function setSalary($salary)
{ $this->salary = $salary; }
public function getName()
{ return $this->getPerson()->getName(); }
public function setName($name)
{ $this->getPerson()->setName($name); }
}
我通常选择这种方法,因为我可以根据情况需要将老师视为简单的老师或人。假设我有两页:一页打印出每个人的姓名(教师和学生),另一页只打印教师和他们的薪水:
// Assume:
// $people = $this->getDoctrine()->getEntityManager()->getRepository("MyBundle:Person")->findAll()
{% for person in people %}
{{ person.name }}
{% endfor %}
// Assume:
// $teachers = $this->getDoctrine()->getEntityManager()->getRepository("MyBundle:Teacher")->findAll()
{% for teacher in teachers %}
{{ teacher.name }} makes ${{ teacher.salary }}
{% endfor %}