在Doctrine中定义关系

时间:2010-11-29 06:03:11

标签: php doctrine many-to-many

我正在尝试为我在Doctrine工作的项目设计一个模型,我想就如何定义不同的关系提出一些建议。

我有3张桌子

场地,系列赛和赛事

  • Venue有许多活动,可以举办有时但不一定是系列活动的活动。
  • 系列是一系列活动,可以始终在同一场地或不同场地进行。
  • 活动必须始终在场地进行,并且可以选择成为系列赛的一部分。

我的理解是,Venue和Series将是一个多对多的关系,因为许多场地可以有很多系列的事件,反之亦然。这种关系是“可选的”会改变一些事实吗?

我也理解这个活动与Venue和Series有一对多的关系,因为一个Venue可以有很多活动,一个系列可以有很多活动,但一个活动只能有一个活动。

我是否以正确的方式看待这一点,并且任何人都可以建议在Doctrine中定义此方法的最佳方法吗?

1 个答案:

答案 0 :(得分:2)

  

你能告诉我你为什么推荐一个   多对多之间的关系   系列和活动。我知道这是   因为它是'可选的'   关系,但我还是有点   混淆为什么这会让它更多   柔性的。

实际上,我感到困惑!我最近一直在使用混合形式的继承,这是有道理的,因为需要构建事物的方式并最大限度地使用引用完整性。您可以轻松地执行以下操作(根据您所说的更符合模型的要求):

Event:
  columns:
    name: string(255)
    venue_id: integer
    series_id: {type: integer, default: null}
  relations:
    Venue:
      local: venue_id
      type:  one
      alias: Venue
      foreign: id
      foreignType: many
      foreignAlias: Events
      onDelete: CASCADE
    Series:
      local: series_id
      type: one
      alias: Series
      foreign: id
      foreignType: many
      foreignAlias: Events
      owningSide: true
      onDelete: SET NULL         

Venue:
 columns:
   name: string(255)
   # other cols

Series:
  columns:
    name: string(255)

尽管如此,使用mm允许您将特定数据添加到refClass或使用多个引用类以获得基本相同的关系(这是我在某些情况下以这种方式执行此操作的方便之处)。所以在技术上它更灵活,但诚然,如果你说的是你唯一的要求,你将永远不需要这种灵活性: - )

  

此外,这是一个事实   那种多对多的关系   需要额外的SeriesEvent   refClass要定义?

  

要从中继续发展,是吗?   必须定义   每当a。这个额外的连接   多对多发生?

无论何时调用集合的访问者,任何教条都不会自动处理。但是,在1-m和m-m的情况下,您通常需要向查询添加连接,以便每次调用访问器时它都不会再次查询数据库。例如:

$events = Doctrine_Core::getTable('Event')->createQuery('e')->execute();
foreach($events as $event){

  // each of the following will query the db so you have  
  // 2*(number of events) queries being issued to the DB in this loop

  $series = $event->getSeries(); // this will join through the ref class automatically
  $venue = $event->getVenue();
}

$events = Doctrine_Core::getTable('Event')->createQuery('e')
  ->leftJoin('e.Series s) // this will join with the ref class automatically
  ->leftJoin(e.Venue v)
  ->execute();

foreach($events as $event){

  // because you explicitly joined the realtion all the data 
  // fetched at once, so this entire loop only uses 1 query.
  $series = $event->getSeries();
  $venue = $event->getVenue();
}

我根本不会将系列和场地联系起来,因为这种关系总是取决于事件,因此不需要相关性。您可以将自己的自定义访问器/ mutators / finders添加到类中,以查询三级关系或从正确的相关对象中提取它。另外因为Event和Series之间的关系是可选的,所以我会使用多对多,因为它允许最大的灵活性。

如下所示:

Event:
  columns:
    name: string(255)
    venue_id: integer
  relations:
    Venue:
      local: venue_id
      type:  one
      alias: Venue
      foreign: id
      foreignType: many
      foreignAlias: Events
      onDelete: CASCADE
    Series:
      local: event_id
      alias: Series
      refClass: SeriesEvent


Venue:
 columns:
   name: string(255)
   # other cols

Series:
  columns:
    name: string(255)
  relations:
    Events:
      local: series_id
      alias: Events
      refClass: SeriesEvents

SeriesEvent:
  columns:
    event_id: {type: integer, primary: true}
    series_id: {type: integer, primary: true}
  relations:
    Series:
      local: series_id
      type: one
      alias: Series
      foreign: id
      foreignType: many
      foreignAlias: SeriesEvents
      onDelete: CASCADE
    Event:
      local: event_id
      type: one
      alias: Event
      foreign: id
      foreignType: many
      foreignAlias: SeriesEvent
      onDelete: CASCADE