2012-11-13 62 views
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什麼列將用於驗證人員是否是教師。 其次是告訴什麼類正在擴展基礎人員類,以及我在前面提到的列。當你這樣做時,你將有兩張表,但在老師中只有你添加到老師實體的數據:)

一般來說,當使用ORM時,你必須考慮對象抽象級別而不關心DB (嗯,這不完全是真的,但它是一般的想法):)

+0

是啊!非常感謝你,這正是我所期待的。 – Ueli

1

不推薦。這裏有幾個原因,我能想到的,爲什麼做到這一點:

  • 如果教師和學生共用同一組ID的,什麼是利用學生的ID加載一個教師,並增加了阻止別人價值到「薪水」字段?限制訪問可以完成,但可能需要定製存儲庫或其他修改。
  • 假設教師需要有薪水。如果學生和老師共享同一個表格,那麼數據庫將無法執行該限制而不給學生太多的薪水。
  • 即使學生永遠不會有薪水,數據庫也可能需要爲該領域分配空間。

IBM有一篇關於mapping inheritance in relational databases的好文章,我在實現這種類型的模型時多次提到過它。他們引用了三種方法:(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 %}