0

我正在尝试使用带有 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从实体(功能、问题等)中获取订阅者(集合)。

4

1 回答 1

2

您可以通过使用带有鉴别器映射的单表继承来实现此订阅表布局。(有关示例,请参阅此博客文章)

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

现在订阅管理器创建一个IssueSubscriptionFeatureSubscription对象并将其持久化。这样,学说将object_type根据您的鉴别器映射正确保存。

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

一种更快的方法可能是使用 IssueSubscription->Issue 和 FeatureSubscription->Feature 关系映射,以这样的表格布局结尾:

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

...然后为您的喜欢添加一个简单的getObject()方法将省略对侦听器的需要。BaseSubscriptionreturn ( $this->feature != null ) ? $this->feature : $this->issue;

于 2013-08-28T13:59:34.950 回答