如何使用Doctrine2处理复合密钥实体的关联?

Dam*_*ien 7 symfony doctrine-orm

假设我有一个可以有1-n范围的优惠.你立刻想到,"把一个offer_id放在Range中".

但我的Offer有一个复合主键(由两个字段组成).没有AUTOINCREMENT id列.

Doctrine2文档没有说明这个特定情况,这是我的实体:

<?php
use Doctrine\ORM\Mapping as ORM;
/**
 * @ORM\Table()
 * @ORM\Entity
 */
class Offer
{
    /**
     * @var Site $site
     * @ORM\Id
     * @ORM\ManyToOne(targetEntity="Site")
     * @ORM\JoinColumn(name="site_id", referencedColumnName="id")
     */
        private $site;

    /**
     * @var string $pouet
     * @ORM\Id
     * @ORM\Column(name="pouet", type="string", length=255)
     */
    private $pouet;
}

<?php
use Doctrine\ORM\Mapping as ORM;

/**
 * @ORM\Table(name="RangeItem")
 * @ORM\Entity
 */
class Range
{
    /**
     * @todo This is test code only do not push me :-)
     * @var ArrayCollection
     * @ORM\ManyToOne(targetEntity="Offer")
     */
    private $offers;
}
Run Code Online (Sandbox Code Playgroud)

我得到了这个错误:

[学说\ ORM\ORMException]
列名id从Pouet\MyBundle \实体\范围向Pouet\MyBundle \实体\发售关系不存在引用.

这是有道理的,但我该如何处理这个问题呢?是否禁止具有复合主键的表在其上具有关联?

小智 8

我相信解决方案是镜像外键(FK)的主键(PK)。对于构成 PK(站点、pouet)的每一列的 IE,您需要在相关实体上具有相同的列。

您可以通过对复合 FK 的每个部分使用JoinColumns注释(或 YAML/XML 中的等效项)JoinColumn来实现此目的:

/**
 * @ORM\Table(name="RangeItem")
 * @ORM\Entity
 */
class Range
{
    /**
     * @todo This is test code only do not push me :-)
     * @var ArrayCollection
     * @ORM\ManyToOne(targetEntity="Offer")
     * @ORM\JoinColumns(
     *     @ORM\JoinColumn(name="site_id", referencedColumnName="site_id"),
     *     @ORM\JoinColumn(name="pouet", referencedColumnName="pouet")
     * )
     */
    private $offers;
}
Run Code Online (Sandbox Code Playgroud)

我希望这可以帮助那些仍在努力解决这个问题的人。


Pro*_*tic 1

您应该能够@JoinColumnRange类中使用注释来指定要使用的 Id:

/**
 * @ORM\ManyToOne(targetEntity="Offer")
 * @ORM\JoinColumn(name="offer_pouet", referencedColumnName="pouet")
 */
private $offers;
Run Code Online (Sandbox Code Playgroud)

因为@JoinColumn如果您不指定它们,则 的默认值将分别为offer_idid,因此您需要手动指定(我在这里做了一些假设,即pouet您的类的唯一值Offer)。

编辑:根据您的评论,我在 Doctrine Project 网站上找到了Composite Primary Key的教程。实体关系有mappedBy一个键和indexBy另一个键。希望有帮助。