2

是否可以(并推荐)为一张桌子使用多个模型?

我有多种类型的“人”(老师、学生、员工、公司),并希望将它们存储在同一张表中。他们拥有所有共同的个人数据,但有其他关系(例如学生 -> 公司、教师 -> 房间等)、附加信息(例如公司:公司名称、教师:教育)等等。

为这种情况获得一些最佳实践会很好。

4

2 回答 2

3

这真的很简单!您必须制作这样的实体:

 /**
 * @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(嗯,这并不完全正确,但这是一般的想法):)

于 2012-11-13T20:42:39.410 回答
2

不建议这样做。以下是我能想到为什么这样做的几个原因:

  • 如果教师和学生共享同一组 ID,如何阻止某人使用学生 ID 加载教师,并在“工资”字段中添加值?可以限制此访问,但可能需要自定义存储库或其他修改。
  • 假设教师必须有薪水。如果学生和教师共享同一个表,那么数据库将无法在不给学生工资的情况下强制执行该约束。
  • 即使学生永远不会有薪水,数据库也可能需要为该字段分配空间。

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 %}
于 2012-11-13T20:02:40.087 回答