2011-04-21 156 views
2

我正在研究使用原則來處理我正在處理的應用程序 - 但是在閱讀完文檔後,我在概念化時遇到了問題,如何表示我們在實體方面的數據庫結構。在Doctrine2中將兩個表映射到一個實體

我有很多表具有夥伴表持有轉換數據,如以下....

Tables ER diagram

在哪裏,我想有一個實體(導航元素),從而不得不進入了「標籤'字段取決於我在應用程序中設置的語言。從教義文檔下似乎表明,你需要定義一個用於保留的實體中的一個(單)表

http://www.doctrine-project.org/docs/orm/2.0/en/reference/basic-mapping.html 默認情況下,該實體將 堅持到表具有相同 名稱作爲類名稱。爲了 變化,你可以使用@Table 註解如下:

或者我需要定義兩個實體並將其鏈接(或允許翻譯表,從元素表繼承)。

我會用什麼樣的策略來總是向Join中插入一個language_id子句(以確保我爲當前設置的語言拉動正確的標籤)。這是我在實體本身或其他地方定義的東西嗎?

回答

2

這似乎適合One-To-Many Bidirectional association。這是從該網頁翻譯成您的具體情況的方案:

/** @Entity */ 
class NavigationElement 
{ 
    // ... 
    /** 
    * @OneToMany(targetEntity="NavigationElementTranslation", mappedBy="navigationElement") 
    */ 
    private $translations; 
    // ... 

    public function __construct() { 
     $this->translations = new \Doctrine\Common\Collections\ArrayCollection(); 
    } 
} 

/** @Entity */ 
class NavigationElementTranslation 
{ 
    // ... 
    /** 
    * @ManyToOne(targetEntity="NavigationElement", inversedBy="translations") 
    * @JoinColumn(name="navigation_element_id", referencedColumnName="id") 
    */ 
    private $navigationElement; 
    // ... 
} 

你可以添加一個getLabel($languageId)方法,通過翻譯進行搜索,以獲取正確的標籤NavigationElement實體:

public function getLabel($languageId) { 

    foreach($this->translations as $trans) { 
     if($trans->languageId == $languageId) 
      return $trans->label; 
    } 

    throw new InvalidArgumentException(); 
} 

,你可以使用下面的DQL,以確保您只想要翻譯裝入$translations屬性:

$query = $em->createQuery(
    "SELECT ne, net 
    FROM Entity\NavigationElement ne 
    JOIN ne.translations net WITH net.languageId = :langId" 
); 
$query->setParameter('langId', $languageId); 
$navigationElements = $query->execute(); 

釷情況聽起來像是你想積極緩存的地方。確保你也看到Doctrine 2's caching機制。

此外,如果您發現用於翻譯的連接表開始變得難以管理,那麼國際化可以在PHP中用gettext合理處理。

+0

對於這個非常好的解釋,我無法感謝你。我想我有一個問題,理解創建一個實體(翻譯)的需要,這個實體(本身)在我的域中沒有意義 - 但是當然,考慮到你提供的例子,我不直接訪問它,但透明,但元素本身。 – calumbrodie 2011-04-22 01:09:00

+0

rojoca的回答相當不錯,但他的最後一句話也是一個很大的暗示。你的直覺是正確的:國際化(I18N)非常棘手,而且從你的領域抽象出這些東西通常會更好。gettext可以非常有用,還有其他機制。例如,ZF的Zend_Locale和Zend_Translate可以在框架之外使用。如果這是一個很大的項目,而且你需要做大量的翻譯工作(並且有時間),我會向後退一步,開始對i18n進行一些研究。 – timdev 2011-04-22 05:13:58

+0

@timdev感謝您的評論。該項目的範圍只是(現在)模擬我們的系統運行的方式*現在*。謝天謝地,它不是很複雜,所以我的解決方案也不需要(我沒有試圖添加那些尚未存在的功能)而且你是對的 - 我對i18n的理解是非常有限的,儘管在這個特定情況下我只需要處理(一些)域對象名稱的簡單翻譯。我會看看你提到的軟件包以及symfony的本地化和國際化功能。 – calumbrodie 2011-04-22 09:18:46

0

我也會引導任何必須解決同樣問題的人來看看下面的原則擴展。

http://www.gediminasm.org/article/translatable-behavior-extension-for-doctrine-2

+3

只需向任何人發出噓聲:上述擴展使用EAV存儲數據,因此對於小數據集以外的其他任何情況都非常低效。如果您有大量需要翻譯的實體,並且您關心性能,那麼您將不得不推出自己的產品。 – calumbrodie 2011-06-16 21:24:30

+0

僅僅因爲使用EAV,你真的可以將某些東西歸類爲「效率極低」嗎?我不是專家,但也許這需要照顧一些性能問題http://www.gediminasm.org/article/translatable-behavior-extension-for-doctrine-2#orm-query-hint – ZolaKt 2011-09-24 10:58:20

+0

@calumbrodie該鏈接處於離線狀態(404);檢查2016-06-08 – feeela 2016-06-08 12:52:39

相關問題