教义中的多对多关系

Posted

技术标签:

【中文标题】教义中的多对多关系【英文标题】:many-to-many relationship in doctrine 【发布时间】:2009-12-08 17:32:39 【问题描述】:

我的系统上有一些表格,如下所示:

news
--id
--title
--content

video
--id
--title
--url

album
--id
--title

现在,我需要以一种灵活的方式与这些表建立多对多关系。我创建了一个名为“链接”的表,其结构如下:

links
--parent_entity (example: news)
--parent_id   (example: 5)
--child_entity (exmaple: video)
--child_id (example: 2)

我如何使用 Doctrine 映射它?

【问题讨论】:

您能解释一下为什么要尝试做不可知映射表之类的事情吗?仅仅是因为您想减少表格数量还是其他原因?使用多对多表提供了一些优势,例如外键约束。 【参考方案1】:

这是不可能的,因为您无法进行正确的连接。这种情况下的连接将取决于 parent_entity 和 child_entity 中的值(即,每一行可能需要连接到不同的表)。此外,学说如何知道要合并哪种记录类型(即,因为它取决于实体类型)。

您可以通过在您的联接上使用 WITH 子句来取消这样的事情(尽管这会很奇怪)。例如,在新闻模型的 setUp() 方法中,您可以这样做:

$this->hasMany('Links as NewsVideoLinks', array('local' => 'id', 'foreign' => 'parent_id'));

在你的链接模型的设置中:

$this->hasMany('Videos as videos', array('local' => 'child_id', 'foreign' => 'id'));

您需要在链接模型中定义所有连接组合。我的意思是,你需要告诉它它有很多新闻和专辑,同时使用 child_id 和 parent_id。

然后在您的查询中,您需要执行以下操作:

$query = Doctrine_Query::create();
$query->from('News n');
$query->innerJoin("n.NewsVideoLinks as links WITH parent_entity = 'news'");
$query->innerJoin("links.Videos as vids WITH child_entity = 'videos'");
$results = $query->execute();

如您所见,这非常麻烦。我强烈建议为每个关系创建连接表。通过加入每个连接表,您仍然可以获得所需的内容。

【讨论】:

【参考方案2】:

Doctrine 的documentation 相当不错。我不太清楚你所说的“灵活”是什么意思,但这里是 Doctrine 版本 1.2 的 Many-To-Many 关系的 yaml 配置示例。

---
User:
  columns:
    id:
      type: integer(4)
      autoincrement: true
      primary: true
    username:
      type: string(255)
    password:
      type: string(255)
  attributes:
    export: all
    validate: true

Group:
  tableName: group_table
  columns:
    id:
      type: integer(4)
      autoincrement: true
      primary: true
    name:
      type: string(255)
  relations:
    Users:
      foreignAlias: Groups
      class: User
      refClass: GroupUser

GroupUser:
  columns:
    group_id:
      type: integer(4)
      primary: true
    user_id:
      type: integer(4)
      primary: true
  relations:
    Group:
      foreignAlias: GroupUsers
    User:
      foreignAlias: GroupUsers

【讨论】:

这是一个简单的多对多。我想要做的是一个表与许多表的关系,就像发布的示例一样。 您可以这样做,但您会失去外键约束的优势,并且必须自己强制执行数据完整性。我不认为教义支持这样的东西,我建议使用传统的多对多表。【参考方案3】:

如果我正确理解您的数据库布局,“parent_entity”和“child_entity”代表您希望将 id 链接到的表。

这是“技术上”不正确的数据库结构(请参阅database normalization),因为您无法将这些列映射到任何其他 single 表列。基本上,您不能使用您的 id现在列,因为它不明确。

我认为您必须重新考虑您的数据库逻辑,然后才能更轻松地编写代码。

【讨论】:

以上是关于教义中的多对多关系的主要内容,如果未能解决你的问题,请参考以下文章

从教义中的多对多自引用实体中获取孩子

教义多对多关系问题

带有额外列的多对多自引用原则

教义 - 在多对多关系表中插入记录

教义2多对多自我引用与中间细节

Access中的多对多关系来自单个表