如何使用 Doctrine 2 创建与额外字段的多对多自引用关联?

Posted

技术标签:

【中文标题】如何使用 Doctrine 2 创建与额外字段的多对多自引用关联?【英文标题】:How to create many-to-many self-referencing association with extra fields by using Doctrine 2? 【发布时间】:2016-09-10 13:58:36 【问题描述】:

思路如下:产品有simplecompound复合产品可能由少数简单产品组成,例如:

有产品“鸡尾酒” - 简单产品,有自己的特点(名称、描述、价格等),还有一个复合 产品 - “鸡尾酒之泉”,其中包含产品 “鸡尾酒” 作为主要组成部分。一个“鸡尾酒喷泉”由 50 个“鸡尾酒”组成。

现在我有 Product 实体,它与 self-referenceing 具有 多对多 关系:

<?php

namespace CT\AppBundle\Entity;

use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\Mapping as ORM;

/**
 * Class Product
 *
 * @ORM\Entity
 * @ORM\Table(name="products")
 */
class Product

    /**
     * @ORM\id
     * @ORM\Column(type="integer")
     * @ORM\GeneratedValue(strategy="AUTO")
     *
     * @var int
     */
    protected $id;

    /**
     * @ORM\Column(type="string")
     *
     * @var string
     */
    protected $name;

    /**
     * @ORM\Column(
     *     name="description",
     *     type="text"
     * )
     *
     * @var string
     */
    protected $desc;

    /**
     * @ORM\Column(type="float")
     *
     * @var float
     */
    protected $price;

    /**
     * @ORM\Column(
     *     name="count_type",
     *     type="string"
     * )
     *
     * @var string
     */
    protected $countType;

    /**
     * @ORM\Column(
     *     name="default_count",
     *     type="integer",
     *     options="unsigned": true
     * )
     *
     * @var int
     */
    protected $defCount;

    /**
     * @ORM\Column(type="boolean")
     *
     * @var bool
     */
    protected $isCountable;

    /**
     * @ORM\Column(type="boolean")
     *
     * @var bool
     */
    protected $isCompound;

    /**
     * @ORM\ManyToMany(
     *     targetEntity="Product",
     *     mappedBy="components"
     * )
     *
     * @var ArrayCollection
     */
    private $products;

    /**
     * @ORM\ManyToMany(
     *     targetEntity="Product",
     *     inversedBy="products"
     * )
     * @ORM\JoinTable(
     *     name="compound_products",
     *     joinColumns=
     *         @ORM\JoinColumn(
     *             name="main_product_id",
     *             referencedColumnName="id"
     *         )
     *     ,
     *     inverseJoinColumns=
     *         @ORM\JoinColumn(
     *             name="component_product_id",
     *             referencedColumnName="id"
     *         )
     *     
     * )
     *
     * @var ArrayCollection
     */
    private $components;

    /**
     * Product constructor.
     */
    public function __construct()
    
        $this->products = new ArrayCollection();
        $this->components = new ArrayCollection();
    

    // Getters & setters...

我想在 compound_products 表中添加额外的字段 amount 来设置一个简单产品的数量复合产品,得到输出:http://prntscr.com/cgdvc3

我找到了一种解决方案,但我不太明白如何将其应用于我的问题:Doctrine many to many self referencing with extra columns

您能否解释一下如何为我的任务添加这个额外的字段,以保存具有自引用的多对多关系?或者如果你有更好的解决方案可以分享吗?

【问题讨论】:

【参考方案1】:

您需要创建一个单独的实体来链接您的实体。 ProductCompound 之类的东西。

然后将它链接到您的 Product 实体两次,对于每个关系。

/**
 * Class ProductCompound
 *
 * @ORM\Entity
 * @ORM\Table(name="compound_products")
 */
class ProductCompound

    /**
     * @ORM\id
     * @ORM\Column(type="integer")
     * @ORM\GeneratedValue(strategy="AUTO")
     *
     * @var int
     */
    protected $id;

    /**
     * @ORM\ManyToOne(
     *     targetEntity="Product",
     *     inversedBy="products"
     * )
     * @ORM\JoinColumn(name="main_product_id", referencedColumnName="id"
     *
     * @var ArrayCollection
     */
    protected $mainProduct;

    /**
     * @ORM\ManyToOne(
     *     targetEntity="Product",
     *     inversedBy="components"
     * )
     * @ORM\JoinColumn(name="component_product_id", referencedColumnName="id"
     *
     * @var ArrayCollection
     */
    protected $componentProduct;

    /**
     * @var double
     *
     * @ORM\Column(name="amount", type="float", nullable=true)
     */
    protected $amount;

并修改产品:

    /**
     * Class Product
     *
     * @ORM\Entity
     * @ORM\Table(name="products")
     */
    class Product
    
...

    /**
     * @ORM\OneToMany(
     *     targetEntity="ProductCompound",
     *     mappedBy="mainProduct"
     * )
     *
     * @var ArrayCollection
     */
    private $productLinks;

    /**
     * @ORM\OneToMany(
     *     targetEntity="ProductCompound",
     *     mappedBy="componentProduct"
     * )
     *
     * @var ArrayCollection
     */
    private $componentLinks;

【讨论】:

感谢您的建议)我想到了同样的解决方案。

以上是关于如何使用 Doctrine 2 创建与额外字段的多对多自引用关联?的主要内容,如果未能解决你的问题,请参考以下文章

如何避免与 Doctrine2 和 Zend Framework 2 的多对多关系重复?

这是在fuelphp中与额外字段创建多对多关系的正确方法吗

与 Shopware 6 中的其他字段的多对多关联

在 django 的多对多关系中添加额外的字段

JPA 2:通过不在带有额外字段的多对多中工作来订购

Doctrine2 中的条件关联