与Doctrine2的多态关系

时间:2011-10-23 22:18:36

标签: php doctrine-orm

如何使用Doctrine 2创建传统的多态关系?

我已经阅读了许多建议使用单表继承的答案,但我无法看到这对我的情况有何帮助。这就是我想要做的事情:

我有一些实用程序实体,如地址,电子邮件和电话号码。

我有一些'可联系'的实体,如客户,雇主,商业。其中每个都应包含与上述实用程序实体的OneToMany关系。

理想情况下,我想创建一个名为'ContactableEntity'的抽象基类,其中包含这些关系,但我知道不可能将OneToMany关系放在带有教义的映射超类中 - 这很好。

但是,如果没有代码中的大量冗余,我仍然不知道如何将它们联系起来。我是否将地址设为STI类型,其中“CustomerAddress”子类包含直接与客户的关系?有没有办法减少重复次数?

2 个答案:

答案 0 :(得分:5)

为什么不让您的基本ContactableEntity具体化?

编辑:

在我完成的使用CTI的项目中做了一些实验。我认为没有任何理由认为同一策略不适用于STI。

基本上,我有类似的东西:

/**                                                                                                                                                                                                                                                                                      
 * Base class for orders.  Actual orders are some subclass of order.                                                                                                                                                                                                                     
 *                                                                                                                                                                                                                                                                                       
 * @Entity                                                                                                                                                                                                             
 * @Table(name="OOrder")                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               
 * @InheritanceType("JOINED")                                                                                                                                                                                                                                                            
 * @DiscriminatorColumn(name="discr", type="string")                                                                                                                                                                                                                                     
 * @DiscriminatorMap({"CAOrder" = "CAOrder", "AmazonOrder" = "AmazonOrder"})                                                                                                                                                                                                                                                                                                                                                                                      
 */
abstract class Order {
    /**           
     * CSRs can add notes to orders of any type                                                                                                                                                                                                                                                          
     * @OneToMany(targetEntity = "OrderNote", mappedBy = "order", cascade={"all"})                                                                                                                                                                                                         
     * @OrderBy({"created" = "ASC"})                                                                                                                                                                                                                                                         
     */
    protected $notes;

    // ...
}

/**                                                                                                                                                                                                                                                                                      
 * @Entity                                                                                                                                                                                                                                                                               
 */
class AmazonOrder extends Order {

  /**                                                                                                                                                                                                                                                                                    
   * @Column(type="string", length="20")                                                                                                                                                                                                                                                 
   */
  protected $amazonOrderId;

  // ...

}

/**                                                                                                                                                                                                                                                                                      
 * @Entity                                                                                                                                                                                                                                                                               
 */
class OrderNote {
    // ...

    /**                                                                                                                                                                                                                                                                                    
     * @ManyToOne(targetEntity="Order", inversedBy="notes")                                                                                                                                                                                                                                
     */
    protected $order;

    // ...
}

它似乎完全符合预期。我可以得到一个OrderNote,它的$order属性将包含一些Order的子类。

使用STI是否有一些限制使您无法做到这一点?如果是这样,我建议转到CTI。但我无法想象为什么这对STI无效。

答案 1 :(得分:0)

如果可联系实体是抽象的(@MappedSuperclass),则您需要使用Doctrine 2.2 +提供的ResolveTargetEntityListener

它基本上允许您通过指定接口而不是具体实体来定义关系。(也许您想要定义/继承几个接口,因为您说的是多个"可联系人和#34 )。例如,您可以在抽象类或具体类中实现接口。最后,您需要将具体类(实体)定义/关联到config.yml中的相关接口

可以在Symfony文档中找到一个示例:http://symfony.com/doc/current/cookbook/doctrine/resolve_target_entity.html