在Doctrine2中将两个表映射到一个实体
我正在研究使用原则来处理我正在处理的应用程序 - 但是在阅读完文档后,我在概念化时遇到了问题,如何表示我们在实体方面的数据库结构。在Doctrine2中将两个表映射到一个实体
我有很多表具有伙伴表持有转换数据,如以下....
在哪里,我想有一个实体(导航元素),从而不得不进入了“标签'字段取决于我在应用程序中设置的语言。从教义文档下似乎表明,你需要定义一个用于保留的实体中的一个(单)表
http://www.doctrine-project.org/docs/orm/2.0/en/reference/basic-mapping.html 默认情况下,该实体将 坚持到表具有相同 名称作为类名称。为了 变化,你可以使用@Table 注解如下:
或者我需要定义两个实体并将其链接(或允许翻译表,从元素表继承)。
我会用什么样的策略来总是向Join中插入一个language_id子句(以确保我为当前设置的语言拉动正确的标签)。这是我在实体本身或其他地方定义的东西吗?
这似乎适合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合理处理。
我也会引导任何必须解决同样问题的人来看看下面的原则扩展。
http://www.gediminasm.org/article/translatable-behavior-extension-for-doctrine-2
只需向任何人发出嘘声:上述扩展使用EAV存储数据,因此对于小数据集以外的其他任何情况都非常低效。如果您有大量需要翻译的实体,并且您关心性能,那么您将不得不推出自己的产品。 – calumbrodie 2011-06-16 21:24:30
仅仅因为使用EAV,你真的可以将某些东西归类为“效率极低”吗?我不是专家,但也许这需要照顾一些性能问题http://www.gediminasm.org/article/translatable-behavior-extension-for-doctrine-2#orm-query-hint – ZolaKt 2011-09-24 10:58:20
@calumbrodie该链接处于离线状态(404);检查2016-06-08 – feeela 2016-06-08 12:52:39
对于这个非常好的解释,我无法感谢你。我想我有一个问题,理解创建一个实体(翻译)的需要,这个实体(本身)在我的域中没有意义 - 但是当然,考虑到你提供的例子,我不直接访问它,但透明,但元素本身。 – calumbrodie 2011-04-22 01:09:00
rojoca的回答相当不错,但他的最后一句话也是一个很大的暗示。你的直觉是正确的:国际化(I18N)非常棘手,而且从你的领域抽象出这些东西通常会更好。gettext可以非常有用,还有其他机制。例如,ZF的Zend_Locale和Zend_Translate可以在框架之外使用。如果这是一个很大的项目,而且你需要做大量的翻译工作(并且有时间),我会向后退一步,开始对i18n进行一些研究。 – timdev 2011-04-22 05:13:58
@timdev感谢您的评论。该项目的范围只是(现在)模拟我们的系统运行的方式*现在*。谢天谢地,它不是很复杂,所以我的解决方案也不需要(我没有试图添加那些尚未存在的功能)而且你是对的 - 我对i18n的理解是非常有限的,尽管在这个特定情况下我只需要处理(一些)域对象名称的简单翻译。我会看看你提到的软件包以及symfony的本地化和国际化功能。 – calumbrodie 2011-04-22 09:18:46