Полиморфные отношения с Doctrine2 - PullRequest
8 голосов
/ 24 октября 2011

Как мне создать традиционные полиморфные отношения с Doctrine 2?

Я прочитал много ответов, в которых предлагается использовать наследование одной таблицы, но я не понимаю, как это поможет в моей ситуации.Вот что я пытаюсь сделать:

У меня есть несколько служебных объектов, таких как Адрес, Электронная почта и PhoneNumber.

У меня есть некоторые «контактные» объекты, такие как Клиент, Работодатель, Бизнес.Каждый из них должен содержать отношение OneToMany с вышеуказанными служебными объектами.

В идеале я хотел бы создать абстрактный базовый класс с именем «ContactableEntity», который содержит эти отношения, но я знаю, что невозможно поставитьОтношения OneToMany в сопоставленных суперклассах с доктриной - это нормально.

Однако я все еще в растерянности из-за того, как я могу связать их без значительной избыточности в коде.Делать ли Address тип STI с подклассом CustomerAddress, который содержит отношение непосредственно к клиенту?Нет ли способа уменьшить количество повторений?

Ответы [ 2 ]

5 голосов
/ 24 октября 2011

Почему бы просто не сделать вашу базу 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.Но я не могу представить, почему это не сработает с ИППП.

0 голосов
/ 19 августа 2015

Если контактная сущность должна быть абстрактной (@MappedSuperclass), вам нужно будет использовать ResolveTargetEntityListener, предоставленный Doctrine 2.2 +.

Она в основном позволяет определить отношение, указавинтерфейс вместо конкретной сущности. (Может быть, вы хотите определить / наследовать несколько интерфейсов, как вы говорите о нескольких «контактных данных»).Например, вы можете реализовать интерфейс в своем абстрактном классе или конкретном классе.Наконец, вам нужно определить / связать конкретный класс (сущность) с соответствующим интерфейсом в config.yml

Пример можно найти в документации Symfony: http://symfony.com/doc/current/cookbook/doctrine/resolve_target_entity.html

...