我正在尝试使用带有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_subscribers
和issue_subscribers
等所有订阅引入单独的表格,或者是否有更优雅的方式?
更新
我不想从订阅方知道目标对象的类型。我只是想从实体(功能,问题等)中获取订阅者(User
的集合)。
答案 0 :(得分:2)
您可以使用带有鉴别器映射的single table inheritance来实现此订阅表布局。 (有关示例,请参阅this blog post)
假设您的订阅管理器服务的subscribe(User $user, SubscriptionObject $object)
方法接收用户对象和要订阅的对象(功能或问题)。
现在订阅管理器会创建一个IssueSubscription
或FeatureSubscription
对象并保留它。这样,学说可以根据您的鉴别器映射正确保存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;
,将省略对听众的需求。