开发者

Defining a relationship in Doctrine

I am experimenting with designing a model for a project I am working on in Doctrine, and I wanted some advice on how I would define different relationships.

I've got 3 tables

Venue, Series and Event

  • Venue has many events, and can host events that are sometimes but not necessarily part of a series.
  • Series is a set of events, which can always occur at the same venue or different venues.
  • Event always has to occur at a venue and can optionally be part of a series.

My understanding is that Venue and Series would be a many-to-many relationship as开发者_JS百科 many venues can have many series of events and vice versa. Does the fact that this relationship is "optional" change things?

I also understand that event would be a one to many relationship with both Venue and Series as one Venue can have many events and one Series can have many events, but an event can only have one of each.

Am I looking at this the correct way, and can anyone advise on the best way to define this within Doctrine?


Can you tell me why you recommend a many-to-many relationship between Series and Events. I get that this is because it is an 'optional' relationship, but I'm still a little confused as to why this makes it more flexible.

Actually, i got confused! Ive been working with mixed forms of inheritance a lot lately where this makes sense because of the way things need to be structured and maximizing the use of referential integrity . You could just as easily do the following i think (which is more inline with the requirements of the model as you stated it):

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)

Still though, using a m-m allows you to add specific data to the refClass or to use multiple reference classes for essentially the same relationship (this is where it was handy for me to do it this way in certain situations). So technically its more flexible, but admittedly if what you stated were your only requirements, you'll never need this flexibility :-)

Also, is it the fact that this is a many-to-many relationship that requires the extra SeriesEvent refClass to be defined?

Yes.

To build on from that, is it necessary to define this additional join whenever a many-to-many occurs?

No doctrine will handle the querting automatically anytime you call an accessor for the collection. However in cases of both 1-m and m-m you will often want to add a join to the query so that everytime you call an accessor it doesnt query the db again. For example:

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

I wouldnt relate Series and Venue at all because the relationship will always depend on an Event thus the correlation is not necessary. You can just add your own custom accessors/mutators/finders to your classes to query for the tertiary relationship or pull it from the proper related objects. Additionally because the relation between Event and Series is optional i would use a many-to-many because it allows for the most flexibility.

Something like the following:

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
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜