将两个表映射到Doctrine2中的一个实体

时间:2011-04-21 08:10:29

标签: orm symfony1 doctrine-orm data-modeling

我正在考虑将doctrine用于我正在处理的应用程序 - 但在阅读完文档之后,我无法概念化如何表示我们在实体方面的数据库结构。

我有很多表都有合作伙伴表,其中包含翻译数据,如下所示....

Tables ER diagram

我希望有一个实体(导航元素)可以访问“标签”字段,具体取决于我在应用程序中设置的语言。 Doctrine文档中的以下内容似乎表明您需要定义一个用于持久化实体的(单个)表

  

http://www.doctrine-project.org/docs/orm/2.0/en/reference/basic-mapping.html   默认情况下,实体将是   坚持到一张桌子一样   将name命名为类名。为了   改变这一点,你可以使用@Table   注释如下:

或者我是否需要定义两个实体并将它们链接起来(或允许转换表继承元素表)。

我将使用什么策略来始终将一个language_id子句插入Join(以确保我为当前设置的语言提取正确的标签)。这是我在实体本身或其他地方定义的东西吗?

2 个答案:

答案 0 :(得分: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;
    // ...
}

您可以向NavigationElement实体添加getLabel($languageId)方法,搜索翻译以获取正确的标签:

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机制。

此外,如果您发现翻译的连接表开始变得无法管理,则可以使用gettext在PHP中合理地处理国际化。

答案 1 :(得分:0)

我还会指示任何必须解决同一问题的人来看看下面的学说扩展。

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