【问题标题】:Doctrine 2 multiple mappedBy?教义2多个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;
    }

    ...

}

【问题讨论】:

    标签: php symfony orm doctrine-orm mapping


    【解决方案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://stackoverflow.com/a/16871539/2853903

      【讨论】:

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