Reputation: 56
When I try to join on an inherited class I get an OutOfBoundsException from Doctrine with the error message above.
I have defined following entities:
FormElement is the parent class
/**
* @ORM\Entity()
* @ORM\InheritanceType("JOINED")
* @ORM\DiscriminatorColumn(name="ETYP_ID", type="integer")
* @ORM\DiscriminatorMap({
* 1 = "DatetimeElement",
* 3 = "ChoiceElement",
* 4 = "TextElement",
* 5 = "MatrixElement",
* 6 = "HtmlElement"
* })
* @Table(name="FORMELEMENT")
*/
abstract class Formelement {
/**
* @var integer
* @ORM\Id()
* @ORM\Column(name="ELE_ID", type="integer", nullable=false)
*/
private $elementId;
}
ChoiceElement is a child class
/**
* @ORM\Entity()
* @ORM\Table(name="CHOICEELEMENT")
*/
class ChoiceElement extends Formelement {
/**
* @var integer
* @ORM\Id()
* @ORM\Column(name="CHOE_ID", type="integer", nullable=false)
*/
private $id;
/**
* @var Choice[]|ArrayCollection
* @ORM\OneToMany(targetEntity="Choice", mappedBy="choiceElement")
*/
private $choices;
public function getChoices(){
return $this->choices;
}
}
And Choice joins on ChoiceElement
/**
* Class Choice
* @package apps\dynfrm\models\Doctrine\entities
* @ORM\Entity()
* @ORM\Table(name="CHOICE")
*/
class Choice {
/**
* @var integer
* @ORM\Id()
* @ORM\Column(name="CHO_ID", type="integer", nullable=false)
*/
private $id;
/**
* @var ChoiceElement
* @ORM\ManyToOne(targetEntity="ChoiceElement", inversedBy="choices")
* @ORM\JoinColumn(name="CHOE_ID", referencedColumnName="CHOE_ID", nullable=false)
*/
private $choiceElement;
}
ChoiceElement
is a FormElement
and has multiple Choice
s. Everything works fine, even the call to ChoiceElement::getChoices()
. When I try to access the resulting ArrayCollection
however, Doctrine throws error mentioned above.
I already did some digging using the debugger, but I don't understand if this is a bug or intended behaviour.
I really hope someone can help me here.
Upvotes: 0
Views: 255
Reputation: 1430
Since ChoiceElement
inherits Formelement
, it does not need to have another id field.
As it is, when doctrine stumbles upon your ChoiceElement
entity, it will define a composite primary key because two fields are marked with the @ORM\Id
annotation which is probably not the behaviour you want. Thus, when it tries to join from your Choice
entity, Doctrine complains because it only has one of the two needed keys that compose the primary key.
To solve this, simply remove the id
attribute of your ChoiceElement
entity. Consequently, don't forget to update the referencedColumnName
attribute of your choiceElement
association. It should now be ELE_ID
and not CHOE_ID
.
Edit: Quick working example:
AbstractA.php
/**
* @ORM\Entity
* @ORM\InheritanceType("JOINED")
* @ORM\DiscriminatorColumn(name="discr", type="integer")
* @ORM\DiscriminatorMap({1 = "A"})
*/
abstract class AbstractA
{
/**
* @ORM\Column(name="id", type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
}
A.php
/** @ORM\Entity() */
class A extends AbstractA
{
/**
* @ORM\OneToMany(targetEntity="B", mappedBy="a")
*/
private $bs;
}
B.php
/** @ORM\Entity() */
class B
{
/**
* @ORM\Column(name="id", type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* @ORM\ManyToOne(targetEntity="A", inversedBy="bs")
*/
private $a;
}
Outputs the following schema:
CREATE TABLE abstract_a (id INT AUTO_INCREMENT NOT NULL, discr INT NOT NULL, PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE = InnoDB;
CREATE TABLE a (id INT NOT NULL, PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE = InnoDB;
CREATE TABLE b (id INT AUTO_INCREMENT NOT NULL, a_id INT DEFAULT NULL, INDEX IDX_71BEEFF93BDE5358 (a_id), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE = InnoDB;
ALTER TABLE a ADD CONSTRAINT FK_E8B7BE43BF396750 FOREIGN KEY (id) REFERENCES abstract_a (id) ON DELETE CASCADE;
ALTER TABLE b ADD CONSTRAINT FK_71BEEFF93BDE5358 FOREIGN KEY (a_id) REFERENCES a (id);
And when I am trying to browse the array collection of B
entities from an A
entity, Doctrine triggers the following query successfully:
SELECT t0.id AS id_1, t0.a_id AS a_id_2 FROM b t0 WHERE t0.a_id = ?
In the same fashion, it is able to join the B
table without a fuss if I ask it to. Here is the query performed when I join a.bs
:
SELECT a0_.id AS id_0, b1_.id AS id_1, a0_.discr AS discr_2, b1_.a_id AS a_id_3
FROM a a2_
INNER JOIN abstract_a a0_ ON a2_.id = a0_.id
INNER JOIN b b1_ ON a2_.id = b1_.a_id
WHERE a0_.id = ?
Upvotes: 1