Doctrine ManyToMany区别领域 - 可能吗?

时间:2013-08-28 13:30:07

标签: php sql symfony doctrine-orm doctrine

我正在尝试使用带有Doctrine 2的单个表/类来实现可应用于多个实体的订阅模型。请参阅下面的示例说明。

架构(yml):

User:
  type: entity
  table: users
  id: int
  name: string

Subscription:
  type: entity
  table: subscriptions
  id: int
  object_type: string
  object_id: int
  user_id: int

Feature:
  type: entity
  table: features
  id: int
  name: string
  manyToMany:
    subscribers:
      targetEntity: User
      joinTable:
        name: subscriptions
        joinColumns:
          object_id:
            referencedColumnName: id

Issue:
  type: entity
  table: issues
  id: int
  subject: string
  manyToMany:
    subscribers:
      targetEntity: User
      joinTable:
        name: subscriptions
        joinColumns:
          object_id:
            referencedColumnName: id

表数据看起来像这样:

users:
| id | name |
| 1  | John |
| 2  | Joe  |

features:
| id | name      |
| 1  | Feature A |
| 2  | Feature B |

issues:
| id | subject |
| 1  | Issue 1 |
| 2  | Issue 2 |

subscriptions:
| id | object_type | object_id | user_id
| 1  | feature     | 1         | 1        <- John is subscribed to Feature A
| 2  | issue       | 1         | 1        <- John is subscribed to Issue 1

我期望得到的是一个额外的“区别”字段,我可以在模型的manyToMany关系中使用,例如:

manyToMany:
  subscribers:
    targetEntity: User
    joinTable:
      name: subscriptions
      joinColumns:
        object_id:
          referencedColumnName: id
        object_type:
          value: feature

我知道后者的灵魂并不存在于学说中,但我很好奇你会如何解决这种情况呢?

我们的想法是将此订阅“特质”动态扩展到其他实体(例如,项目,团队等)

我是否必须为feature_subscribersissue_subscribers等所有订阅引入单独的表格,或者是否有更优雅的方式?

更新

我不想从订阅方知道目标对象的类型。我只是想从实体(功能,问题等)中获取订阅者(User的集合)。

1 个答案:

答案 0 :(得分:2)

您可以使用带有鉴别器映射的single table inheritance来实现此订阅表布局。 (有关示例,请参阅this blog post

假设您的订阅管理器服务的subscribe(User $user, SubscriptionObject $object)方法接收用户对象和要订阅的对象(功能或问题)。

现在订阅管理器会创建一个IssueSubscriptionFeatureSubscription对象并保留它。这样,学说可以根据您的鉴别器映射正确保存object_type

最后,您必须添加一个侦听器/订阅者,以动态调整***订阅对象的关系映射(与问题或功能的关系),以便将外键始终保存到object_id

更快捷的方法可能就是使用IssueSubscription-&gt; Issue和FeatureSubscription-&gt;以表布局结尾的特征关系映射,如下所示:

subscriptions:
| id | object_type | feature_id | issue_id  | user_id
| 1  | feature     | 1          | NULL      | 1 
| 2  | issue       | NULL       | 1         | 1 

...然后向您的getObject()添加一个简单的BaseSubscription方法,例如return ( $this->feature != null ) ? $this->feature : $this->issue;,将省略对听众的需求。