2011-04-21 175 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

相关问题