1

I have a question similar to this one.

I need a relation one-to-one through composite key, is it possible? I've read about this but it's referred to one-to-many relation

class Header{
    /**
     * 
     * @ORM\Id
     * @ORM\Column(name="UH1", type="integer", nullable=false)
     */
    protected $key1;

    /**
     * 
     * @ORM\Id
     * @ORM\Column(name="UH2", type="integer", nullable=false)
     */
    protected $key2;

    /**
     * @ORM\OneToOne(targetEntity="Detail", mappedBy="header")
     */
    protected $detail;
} 

class Detail{
/**
     * 
     * @ORM\Id
     * @ORM\Column(name="UD1", type="integer", nullable=false)
     */
    protected $key1;

    /**
     * 
     * @ORM\Id
     * @ORM\Column(name="UD2", type="integer", nullable=false)
     */
    protected $key2;

    /**
     * @ORM\OneToOne(targetEntity="Header", inversedBy="detail")
     */
    protected $header;
}

I mean there are two columns as Id per entity... do i need to add the joincolumn ?

Jack Skeletron
  • 1,351
  • 13
  • 37

1 Answers1

2

You need to use the JoinColumns annotation that allows to define an array of JoinColumn annotations to handle such cases for ManyToOne or OneToOne associations.

With the following entities:

AppBundle\Entity\A.php

namespace AppBundle\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
 * @ORM\Entity()
 */
class A
{
    /**
     * @ORM\Id
     * @ORM\Column(name="key1", type="integer", nullable=false)
     */
    private $key1;

    /**
     * @ORM\Id
     * @ORM\Column(name="key2", type="integer", nullable=false)
     */
    private $key2;

    /**
     * @ORM\OneToOne(targetEntity="AppBundle\Entity\B", mappedBy="a")
     * @ORM\JoinColumns(
     *      @ORM\JoinColumn(name="key1", referencedColumnName="key1"),
     *      @ORM\JoinColumn(name="key2", referencedColumnName="key2"),
     * )
     */
    private $b;
}

AppBundle\Entity\B.php

namespace AppBundle\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
 * @ORM\Entity()
 */
class B
{
    /**
     * @ORM\Id
     * @ORM\Column(name="key1", type="integer", nullable=false)
     */
    private $key1;

    /**
     * @ORM\Id
     * @ORM\Column(name="key2", type="integer", nullable=false)
     */
    private $key2;

    /**
     * @ORM\OneToOne(targetEntity="AppBundle\Entity\A", inversedBy="b")
     * @ORM\JoinColumns(
     *      @ORM\JoinColumn(name="key1", referencedColumnName="key1"),
     *      @ORM\JoinColumn(name="key2", referencedColumnName="key2"),
     * )
     */
    private $a;
}

I could achieve the desired behaviour. When asked for a schema update, Doctrine outputs:

CREATE TABLE a (key1 INT NOT NULL, key2 INT NOT NULL, UNIQUE INDEX b_uniq (key1, key2), PRIMARY KEY(key1, key2)) DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE = InnoDB;
CREATE TABLE b (key1 INT NOT NULL, key2 INT NOT NULL, UNIQUE INDEX a_uniq (key1, key2), PRIMARY KEY(key1, key2)) DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE = InnoDB;
ALTER TABLE a ADD CONSTRAINT FK_E8B7BE432C5C6450B55535EA FOREIGN KEY (key1, key2) REFERENCES b (key1, key2);
ALTER TABLE b ADD CONSTRAINT FK_71BEEFF92C5C6450B55535EA FOREIGN KEY (key1, key2) REFERENCES a (key1, key2);
Alan T.
  • 1,382
  • 1
  • 7
  • 14
  • Thank you, i've used the JoinColumns, this is my situation now (https://pastebin.com/PwYYW0Y5). The fact is that i have primary key columns used also as foreign key (no b_key* or a_key*), this is an existent database and i'm trying to write the correct Entity. Now i have an error `Missing value for primary key UD1 on Details` – Jack Skeletron Jan 31 '18 at 13:40
  • 1
    @JackSkeletron You are not using the right syntax for `JoinColumns`. It needs to be `@ORM\JoinColumns(...)` and not `@ORM\JoinColumns={...}`. Curiously, Doctrine will not consider it as an error but the output given for the schema update will only consider one field instead of two. I updated my answer so that it can fit your specific use case. The schema given by Doctrine contains, as expected, only two fields for A and B which are then marked as foreign keys. – Alan T. Jan 31 '18 at 13:56
  • thank you very much! It worked, i've read about that notation [here](http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/annotations-reference.html#annref-joincolumns) – Jack Skeletron Jan 31 '18 at 14:16
  • Ah I see. I think you mixed up the example given there that was about the `joinColumns` attribute of the `JoinTable` annotation with the `JoinColumns` annotation section which does not have any example at all. Either way, glad that I could help :) – Alan T. Jan 31 '18 at 14:21