当我尝试加入一个继承的类时,我从Doctrine获得一个OutOfBoundsException并带有上面的错误信息。
我定义了以下实体:
FormElement是父类
/**
* @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是一个子类
/**
* @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;
}
}
Choice加入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
是FormElement
,有多个Choice
。一切正常,甚至拨打ChoiceElement::getChoices()
。但是,当我尝试访问生成的ArrayCollection
时,Doctrine会抛出上面提到的错误。
我已经使用调试器进行了一些挖掘,但我不明白这是一个错误还是预期的行为。
我真的希望有人能在这里帮助我。
答案 0 :(得分:0)
由于ChoiceElement
继承了Formelement
,因此不需要另外的id字段。
实际上,当教义偶然发现你的ChoiceElement
实体时,它会定义一个复合主键,因为两个字段都标有@ORM\Id
注释,这可能不是你想要的行为。因此,当它尝试从您的Choice
实体加入时,Doctrine会抱怨,因为它只有构成主键的两个必需键之一。
要解决此问题,只需删除id
实体的ChoiceElement
属性即可。因此,请勿忘记更新referencedColumnName
关联的choiceElement
属性。它现在应该是ELE_ID
而不是CHOE_ID
。
修改:快速工作示例:
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;
}
输出以下架构:
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);
当我尝试从B
实体浏览A
个实体的数组时,Doctrine会成功触发以下查询:
SELECT t0.id AS id_1, t0.a_id AS a_id_2 FROM b t0 WHERE t0.a_id = ?
以同样的方式,如果我要求,它可以毫不费力地加入B
表。以下是我加入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 = ?