Search code examples
symfonydoctrine-ormsymfony-2.3

Generate ID keys in a table with composite keys using Doctrine2 and Symfony2


I have some tables in my DB with composite keys, see the picture below:

Tables with composite keys

As you can see in this case are interest and klists which have their own id but also has kuser as key also. Doctrine docs says that they support almost every uses case in composite keys but every entity with a composite key cannot use an id generator other than “ASSIGNED”. That means the ID fields have to have their values set before you call EntityManager#persist($entity). When I try to define any of the entities related to those tables I got a error because Doctrine doesn't allow to have this:

  /**
   * @ORM\Id
   * @ORM\Column(name="id", type="integer", nullable=false)
   * @ORM\GeneratedValue(strategy="AUTO")
   */
  protected $id;

  /**
   * @ORM\Id      
   * @ORM\ManyToOne(targetEntity="UserBundle\Entity\User", inversedBy="users" )      
   * @ORM\JoinColumn(name="kuser", referencedColumnName="id")   
   */
   protected $kuser; 

I know that I can run some code using life-cycle callback but don't know how or where so I need some help here, any can tell me or point me in the right path?


Solution

  • Back to basics. I'd suggest starting here: http://docs.doctrine-project.org/en/latest/reference/association-mapping.html

    class KUser
    {
        /**
         * @ORM\Id
         * @ORM\Column(name="id", type="integer", nullable=false)
         * @ORM\GeneratedValue(strategy="AUTO")
         */
        protected $id;
    
    class Interest
    {
          /**
           * @ORM\Id
           * @ORM\Column(name="id", type="integer", nullable=false)
           * @ORM\GeneratedValue(strategy="AUTO")
           */
          protected $id;
    
          /**      
           * @ORM\ManyToOne(targetEntity="UserBundle\Entity\KUser")      
           * @ORM\JoinColumn(name="kuser_id", referencedColumnName="id")   
           */
          protected $kuser; 
    

    That is all you need to establish a one-way ManyToOne relation between Interest and KUser. If you need it bi-directional then add an $interests property to KUser and set the inversedBy in Interest.kuser

    Make sure you understand the simple relations before proceeding.

    Doctrine will auto-generate a ManyToMany link table if the link table has no additional properties. Your KUserHasKLists does have additional attributes. So you need to make it an entity and then use ManyToOne relations to link the the other tables. And while technically you could probably still use a composite key here, it's much easier to just define an auto-increment primary key.

    class KUserHasKLists
    {
          /**
           * @ORM\Id
           * @ORM\Column(name="id", type="integer", nullable=false)
           * @ORM\GeneratedValue(strategy="AUTO")
           */
          protected $id;
    
          /**      
           * @ORM\ManyToOne(targetEntity="UserBundle\Entity\KUser")      
           * @ORM\JoinColumn(name="kuser_id", referencedColumnName="id")   
           */
          protected $kuser; 
    
          /**      
           * @ORM\ManyToOne(targetEntity="UserBundle\Entity\KList")      
           * @ORM\JoinColumn(name="klist_id", referencedColumnName="id")   
           */
          protected $klist; 
    

    But again, start with a simple relation and make sure you understand what is happening. Make yourself some functional tests if you are comfortable with phpunit. If not, make yourself a Symfony Command so you can experiment with this stuff from the command line.