title: ManyToMany associations between several "content type" entities and one "media" entity
body: <p>Using Symfony 2.5+ and Doctrine 2.2+, is it a bad idea to create multiple entities which all have a ManyToMany association with one other single shared entity? </p>
  
  <h2>Background</h2>
  
  <p>Put on your thinking caps :) I am building 2.0 of our <a href="http://www.gutensite.com" rel="nofollow">existing CMS</a> in Symfony 2.5 where we have many different "Content Types", e.g. Article, Profile, Map, Image, Video, Document, etc. When users create a new piece of content (based on one of these content types) they may choose images to associate with that content (yes the image is a content type as well). </p>
  
  <p>The content types are really a CMS construct for making it easier for people to add content to the site. Each content type has a <code>controller</code> which determines what entity the content type maps to. For the most part, each content type has it's own <code>entity</code> for persisting the data. The image, document and video content types are a little different in that they all map to a shared <code>media</code> entity (so that I can easily manage the cloud storage for all these files from one table, since they are all essentially "media" and the content type distinction is largely just UI).</p>
  
  <p>So my plan is to make a bidirectional <code>ManyToMany</code> association between each content type entity (e.g. <code>Articles</code>) and the <code>Media</code> entity. So that when someone selects an image to associate with an article, the association is mapped in a join table <code>article_media</code>. This will allow us to find all content where an image is in use, so that we don't delete an active image (or at least make sure they explicitly agree).</p>
  
  <p>For the sake of simplification, we'll just map one <code>$media</code> association, instead of separate ones for images, documents and videos, which could also be associated with an article (I think we will handle this with a controller that extracts the full Media list for separate form inputs and then merges them back into the Media array for persistence, so that we don't have to make multiple calls to the database).</p>
  
  <p>This requires that the <code>Article</code> entity have an association like this:</p>
  
  <pre><code>/**
   *
   * @ORM\ManyToMany(targetEntity="\Gutensite\MediaBundle\Entity\Media", inversedBy="version", cascade={"persist", "remove"})
   * @ORM\JoinTable(name="article_media")
   */
  protected $media;
  </code></pre>
  
  <p>And the <code>Media</code> Entity will have an inverse association like this:</p>
  
  <pre><code>/**
   * @ORM\ManyToMany(targetEntity="\Gutensite\ArticleBundle\Entity\Article", mappedBy=“media”)
   */
  protected $article;
  </code></pre>
  
  <p>But if I have multiple content types, each entity will need this as well, and so soon the <code>Media</code> entity will have a lot of additional associations:</p>
  
  <pre><code>// Article Association plus additional ones for each entity...
  
  /**
   * @ORM\ManyToMany(targetEntity="\Gutensite\ProfileBundle\Entity\Profile", mappedBy=“media”)
   */
  protected $profile;
  
  /**
   * This is self referential since a video may need to specify a thumbnail image...
   * I'm not sure yet how best to do this, but it will be necessary.
   * @ORM\ManyToMany(targetEntity="\Gutensite\MediaBundle\Entity\Media", mappedBy=“media”)
   */
  protected $media;
  
  // ...etc...
  </code></pre>
  
  <p>This would end up creating unique join tables for <strong>every</strong> content type, e.g. <code>article_media</code>, <code>profile_media</code>, <code>media_media</code>. That is probably nice for keeping these tables smaller.</p>
  
  <h2>Cons</h2>
  
  <p>The downside of this is that everytime we create a new content type, we have to add an additional association on the Media entity. If we start to get 10+ content types, that's a lot of associations. Is that a problem? </p>
  
  <p>Any other problems?</p>
  
  <h2>Alternatives</h2>
  
  <p>Is it possible to make the join table have a <code>entity</code> field that indicates the content type, so that we only have one join table for all the different content types? For example:</p>
  
  <pre><code>id | entity | entityId | MediaId
  </code></pre>
  
  <p>If so how would you define in Doctrine this extra <code>entity</code> distinction field to prevent collisions with <code>entityId</code> for different content types?</p>
  
  <h2>Other Considerations</h2>
  
  <p>Later when we allow third party developers to create their own content types, this solution will no longer work because we don't want there to be hundreds of associations. So in this case, we thought that we would create an intermediate entity like <code>MediaMap</code>. Each entity will have a OneToMany relationship with <code>MediaMap</code> (uni-directional so that we only have to define the inverese side on <code>MediaMap</code> back to every content type). And then <code>MediaMap</code> will have a ManyToMany relationship with <code>Media</code> with a join table in between. That way <code>Media</code> will only maintain one association to the <code>MediaMap</code>.</p>
  
  <p>This seems a bit cumbersome, and introduces another database query into the sequence, which I don't at all like.</p>
  
  <h2>Solutions</h2>
  
  <p>So is there a better way to do this?</p>
  
  <p>Should we just maintain our own <code>MediaMap</code> table manually, and not rely on Doctrine entity association?</p>