Search code examples
doctrinejunction-tablediscriminator

discriminator in junction table with Doctrine


I have a number of unrelated entities that I'd like to be able to add FileAttachment entities to. I'm using Doctrine2 (in the context of a Symfony project).

Before I started using Doctrine, I'd make a junction table with a discriminator column, like this:

file_id
entity_id
entity_type

So far as I can tell, with Doctrine I'll require a junction table for each entity type that has FileAttachment associations. I'd prefer to avoid that if possible. I found an NHibernate solution here. Is it possible to do something similar with Doctrine and can anybody point me at some documentation? I've read (umpty times now!) chapters 6 and 7 of the Doctrine manual. But I'm not finding what I'm looking for.


Solution

  • Try creating an abstract FileAttachment class and extending it for each entity_type i.e. EntityOneAttachment, EntityTwoAttachment, etc.

    The extended classes will all refer to the same join column entity_id but map it to their respective entities.

    /**
     * @ORM\Entity
     * @ORM\Table(name="file_attachment")
     * @ORM\InheritanceType("SINGLE_TABLE")
     * @ORM\DiscriminatorColumn(name="entity_type", type="string")
     * @ORM\DiscriminatorMap({"entity_one_attachment" = "EntityOneAttachment", "entity_two" = "EntityTwoAttachment"})
     */
    abstract class FileAttachment
    {          
      /**
       * @ORM\ManyToOne(targetEntity="File")
       * @ORM\JoinColumn(name="file_id", referencedColumnName="id", nullable=false)
      **/  
      protected $file;
    }
    
    /**
     * @ORM\Entity
     */
    class EntityOneAttachment extends FileAttachment
    {
      /**
       * @ORM\ManyToOne(targetEntity="EntityOne", inversedBy="fileAttachments")
       * @ORM\JoinColumn(name="entity_id", referencedColumnName="id", nullable=false)
      **/        
      protected $entityOne;
    }
    
    /** 
     * @ORM\Entity 
     */
    class EntityTwoAttachment extends FileAttachment
    {
      /**
       * @ORM\ManyToOne(targetEntity="EntityTwo", inversedBy="fileAttachments")
       * @ORM\JoinColumn(name="entity_id", referencedColumnName="id", nullable=false)
      **/        
      protected $entityTwo;  
    }
    

    Then map each Entity to its respective Attachment class.

    class EntityOne
    {
      /**
       * @ORM\OneToMany(targetEntity="EntityOneAttachment", mappedBy="entityOne")
      **/        
      protected $fileAttachments;
    }