教义2多个mappedBy?

Posted

技术标签:

【中文标题】教义2多个mappedBy?【英文标题】:Doctrine 2 multiple mappedBy? 【发布时间】:2015-09-25 21:44:14 【问题描述】:

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

我有一个CashRegister 实体,它有一个垃圾箱位置和一个回收箱位置。两个位置都来自同一类型(BinLocation Entity)。

CashRegisterCashRegister->getBinLocations()CashRegister->getReturnBinLocations() 传出工作正常,但我怎样才能实现BinLocation->getCashRegisters() 返回所有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;
    

    ...


【问题讨论】:

【参考方案1】:

我还搜索了解决方案并为 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;


【讨论】:

【参考方案2】:

简单的答案是你不能。 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 合并的灵感来自这里:https://***.com/a/16871539/2853903

【讨论】:

感谢 Mark 的回答,但这个解决方案看起来有点像 hack。在谷歌搜索了一段时间后(在我写这个问题之前),我注意到只有少数人有同样的问题。是否有可能以更(企业)“教条”的方式实现它的另一种方法? (类,表,一切都可以更改,唯一的要求是我可以将 bin 位置和返回 bin 位置存储到收银机并正确取回) 问题出在不能指定多个mappedBy字段。因此,您需要使用 Doctrine 为您提供的其他功能来解决问题,上面提供了一个示例。如果您想要核心 Doctrine 功能更改,可以尝试在 Github 上请求它们?但是在这个阶段,您将获得的所有解决方案都将是“hacky”:)

以上是关于教义2多个mappedBy?的主要内容,如果未能解决你的问题,请参考以下文章

教义 2 OneToMany 级联设置 NULL

教义自引用关联映射(Symfony)

hibernate的注解属性mappedBy详解

hibernate的注解属性mappedBy详解

Symfony2 教义连接返回太多数据

使用 joinColumn 而不是 mappedBy 有啥危害?