Определение отношений в Доктрине - PullRequest
0 голосов
/ 29 ноября 2010

Я экспериментирую с разработкой модели для проекта, над которым я работаю в Doctrine, и хотел получить несколько советов о том, как определить различные отношения.

У меня 3 стола

Место, серия и событие

  • Место проведения имеет много событий и может принимать события, которые иногда, но не обязательно, являются частью серии.
  • Серия - это набор событий, которые всегда могут происходить в одном и том же месте или в разных местах.
  • Событие всегда должно происходить в месте проведения и при желании может быть частью серии.

Насколько я понимаю, место проведения и серия будут отношениями "многие ко многим", так как на многих объектах может быть много серий событий и наоборот. Меняет ли факт, что эти отношения являются «необязательными»?

Я также понимаю, что событие может быть отношением один ко многим как с Местом проведения, так и с Серией, поскольку одно Место может иметь много событий, а в одной Серии может быть много событий, но у события может быть только одно из каждого.

Правильно ли я смотрю на это, и может ли кто-нибудь посоветовать, как лучше определить это в Учении?

1 Ответ

2 голосов
/ 29 ноября 2010

Можете ли вы сказать мне, почему вы рекомендуете отношения многих ко многим Серия и События. Я понимаю, что это потому что это «необязательно» отношения, но я все еще немного запутался, почему это делает его более гибкий.

На самом деле, я запутался! В последнее время я много работал со смешанными формами наследования, где это имеет смысл из-за того, как вещи должны быть структурированы и максимально использовать ссылочную целостность. Я думаю, вы могли бы так же легко сделать следующее (что больше соответствует требованиям модели, как вы ее указали):

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)

Тем не менее, использование m-m позволяет вам добавлять конкретные данные в refClass или использовать несколько ссылочных классов по существу для одной и той же связи (именно здесь мне было удобно делать это таким образом в определенных ситуациях). Технически это более гибко, но по общему признанию, если то, что вы заявили, были вашими единственными требованиями, вам никогда не понадобится такая гибкость: -)

Кроме того, тот факт, что это отношения многие ко многим, требует дополнительного SeriesEvent refClass, который будет определен?

Да.

Основываясь на этом, это правда? необходимо определить это дополнительное соединение всякий раз, когда происходит много ко многим?

Ни одна доктрина не будет обрабатывать запросы автоматически каждый раз, когда вы вызываете метод доступа к коллекции. Однако в случаях как 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();
}

Я бы вообще не связывал Серию и Место проведения, потому что отношения всегда будут зависеть от События, поэтому корреляция не нужна. Вы можете просто добавить свои собственные аксессоры / мутаторы / искатели к своим классам, чтобы запросить третичные отношения или извлечь их из соответствующих связанных объектов. Кроме того, поскольку связь между Событием и Серией является необязательной, я бы использовал «многие ко многим», поскольку она обеспечивает большую гибкость.

Примерно так:

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
...