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

发布于 2024-11-02 12:23:21 字数 701 浏览 6 评论 0原文

我正在考虑将学说用于我正在开发的应用程序 - 但在阅读文档后,我很难概念化如何用实体来表示我们拥有的数据库结构。

我有很多表,其中有合作伙伴表,其中保存如下所示的翻译数据...

Tables ER 图

我想要的位置拥有一个可以访问“标签”字段的实体(导航元素),具体取决于我在应用程序中设置的语言。 Doctrine 文档中的以下内容似乎建议您需要定义一个(单个)表来保存实体

http://www.doctrine -project.org/docs/orm/2.0/en/reference/basic-mapping.html 默认情况下,该实体将是 持久化到具有相同的表 name 作为类名。为了 改变它,你可以使用@Table 注释如下:

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

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

I'm looking at using doctrine for an application I'm working on - but after reading the documentation I'm having trouble conceptualizing how to represent the database structure we have in terms of entities.

I have many tables which have partner tables which hold translation data like the following....

Tables ER diagram

Where I would like to have one Entity (Navigation Element) which had access to the 'label' field depending on what Language I set in my application. The following from the Doctrine documentation seems to suggest that you need to define one (single) table which is used to persist an entity

http://www.doctrine-project.org/docs/orm/2.0/en/reference/basic-mapping.html
By default, the entity will be
persisted to a table with the same
name as the class name. In order to
change that, you can use the @Table
annotation as follows:

Or do I need to define two entities and link them (or allow the translation table to inherit from the element table).

And what strategy would I use to always insert a language_id clause to the Join (to ensure I'm pulling the right label for the currently set language). Is this something I would define in the entity itself, or elsewhere?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

被你宠の有点坏 2024-11-09 12:23:21

这似乎适合 一对多双向关联。这是该页面翻译为您的情况的场景:

/** @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 的缓存机制也。

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

This seems to suit a One-To-Many Bidirectional association. This is the scenario from that page translated to your situation:

/** @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;
    // ...
}

You could add a getLabel($languageId) method to the NavigationElement entity that searches through the translations to get the correct label:

public function getLabel($languageId) {

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

    throw new InvalidArgumentException();
}

And you could use the following DQL to ensure you only load the translation you want into the $translations property:

$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();
         

This situation sounds like one where you would want to cache aggressively. Make sure you look into Doctrine 2's caching mechanisms too.

Also, internationalization can be handled reasonably well in PHP with gettext if you find join tables for translations start to become unmanageable.

九歌凝 2024-11-09 12:23:21

我还建议任何必须解决同样问题的人看一下以下学说扩展。

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

I would also direct anyone who has to tackle this same problem to take a look at the following doctrine extension.

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文