Doctrine 2 multiple mappedBy?

Doctrine 2 multiple mappedBy?

我在正确设置 Doctrine 映射时遇到问题。

我有一个 CashRegister 实体,它有一个库位和一个 return 库位。两个位置都来自同一类型(BinLocation 实体)。

来自 CashRegisterCashRegister->getBinLocations()CashRegister->getReturnBinLocations() 的传出工作正常,但我如何实现 BinLocation->getCashRegisters() return 全部 CashRegister 引用的实体 (binLocation + returnBinLocation)?

/**
 * CashRegister
 *
 * @ORM\Table(name="cash_registers")
 * @ORM\Entity
 * @ORM\HasLifecycleCallbacks
 */
class CashRegister
{

    ...

    /**
     * @var BinLocation
     *
     * @ORM\ManyToOne(targetEntity="BinLocation", inversedBy="cashRegisters")
     * @ORM\JoinColumn(name="bin_location_id", referencedColumnName="id")
     */
    private $binLocation;

    /**
     * @var BinLocation
     *
     * @ORM\ManyToOne(targetEntity="BinLocation", inversedBy="cashRegisters")
     * @ORM\JoinColumn(name="return_bin_location_id", referencedColumnName="id")
     */
    private $returnBinLocation;


    /**
     * @return BinLocation
     */
    public function getBinLocation()
    {
        return $this->binLocation;
    }

    /**
     * @return BinLocation
     */
    public function getReturnBinLocation()
    {
        return $this->returnBinLocation;
    }

    ...

}

/**
 * BinLocation
 *
 * @ORM\Table(name="bin_locations")
 * @ORM\Entity
 * @ORM\HasLifecycleCallbacks
 */
class BinLocation
{

    ...

    /**
     * @var CashRegister[]
     *
     * @ORM\OneToMany(targetEntity="CashRegister", mappedBy="binLocation") <= Here is the problem, in this case mappedBy need to be an array [binLocation, returnBinLocation]
     */
    private $cashRegisters;


    /**
     * @return CashRegister[]
     */
    public function getCashRegisters()
    {
        return $this->cashRegisters;
    }

    ...

}

简单的回答是你不能。 mappedBy 只接受一个参数。

实现您想要的解决方案非常简单。在 BinLocation 中创建第二个 属性 名为:cashRegisters2,如下所示:

/**
 * @var CashRegister[]
 *
 * @ORM\OneToMany(targetEntity="CashRegister", mappedBy="binLocation")
 */
private $cashRegisters;

/**
 * @var CashRegister[]
 *
 * @ORM\OneToMany(targetEntity="CashRegister", mappedBy="binLocation") 
 */
private $cashRegisters2;

然后在您的 getCashRegisters 方法中合并集合。

/**
 * @return CashRegister[]
 */
public function getCashRegisters()
{
    return new ArrayCollection(
                      array_merge($cashRegisters->toArray(), $cashRegisters2->toArray())
    );
}

同时相应地更改您的 CashRegister 映射:

/**
 * @var BinLocation
 *
 * @ORM\ManyToOne(targetEntity="BinLocation", inversedBy="cashRegisters")
 * @ORM\JoinColumn(name="bin_location_id", referencedColumnName="id")
 */
private $binLocation;

/**
 * @var BinLocation
 *
 * @ORM\ManyToOne(targetEntity="BinLocation", inversedBy="cashRegisters2")
 * @ORM\JoinColumn(name="return_bin_location_id", referencedColumnName="id")
 */
private $returnBinLocation;

注意:我没有测试代码。此示例仅用于服务器指南。

注2: ArrayCollection合并的灵感来自这里:

我还搜索了解决方案并为 Doctrine 制作了一个补丁,这样您就可以 custom_attributes 链接到各种实体类型。

学说 2.6:https://github.com/danielbeeke/doctrine2/commit/2d8530176b872cb490c5c88b8c8e17d8d0091388 学说 2.7:https://github.com/danielbeeke/doctrine2/commit/5bde696848ea9fe7035fadc4d46baa4c0d51f3a2

/**
 * @Entity
 * @Table(name="product")
 * @HasLifecycleCallbacks
 **/
class Product {

  /**
   * One Product has Many Attributes.
   *
   * @OneToMany(
   *   targetEntity="CustomAttribute",
   *   mappedBy="EntityId",
   *   mappedByType={
   *     "field": "EntityType",
   *     "value": "product"
   *   }
   * )
   *
   * @var $CustomAttributes ArrayCollection
   */
  protected $CustomAttributes;
}


/**
 * @Entity
 * @Table(name="custom_attribute")
 * @HasLifecycleCallbacks
 **/
class CustomAttribute_entity {

  /** @Id @Column(type="integer") @GeneratedValue */
  protected $Id;

  /**
   * Many Attributes have One Entity of the EntityType provided.
   * @ManyToOne(targetEntity="Product", inversedBy="CustomAttributes")
   * @JoinColumn(name="EntityId", referencedColumnName="Id")
   */
  protected $EntityId;

  /** @Column(type="string") */
  protected $EntityType;

  /** @Column(type="string") */
  protected $Type;

  /** @Column(type="string") */
  protected $Value;

}