2013-08-28 67 views
0

我試圖實現一個訂閱模型,可以應用於多個實體使用單個表/類與教條2.請參見下面的示例解釋。學說ManyToMany區分字段 - 可能嗎?

架構(陽明):

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所有訂閱。等等,還是有更優雅的方式?

UPDATE:

我不想認購方目標對象的種類就知道了。我只是想要從實體(特徵,問題等)中獲取訂閱者(User的集合)。

+0

這種情況下,Mapped Superclasses可能出現在哪裏? –

+0

你是什麼意思?「我只是想從實體(特徵,問題等)中獲取訂閱者(用戶的集合)。」 ...你在尋找查詢來查找所有用戶的問題/功能嗎?請澄清:) – nifr

+0

我的意思是我不會查詢不同類型的對象的訂閱。即我不願意使用Doctrine根據Subscription對象自動獲取適當的對象/實體(如問題或功能)。 我正在尋找一個功能或問題對象的訂閱用戶列表,例如'$ feature-> getSubscribers()'或'$ issue-> getSubscribers()' –

回答

2

您可以通過使用帶鑑別器映射的single table inheritance來實現此訂閱表格佈局。 (例如,參見this blog post

假設您的訂閱管理器服務的subscribe(User $user, SubscriptionObject $object)方法接收用戶對象和要訂閱的對象(功能或問題)。

現在訂閱管理器創建一個IssueSubscriptionFeatureSubscription對象並保留它。這種方式的原則會根據您的鑑別器地圖正確保存object_type

最後,您必須添加一個偵聽器/訂閱者,以動態調整***訂閱對象的關係映射(與問題或功能的關係),以便始終將外部關鍵字保存到object_id

更快的方法可能只使用IssueSubscription->問題和FeatureSubscription->在一個表格佈局這樣的結局功能關係映射:

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;將忽略對聽者的需要。

+0

謝謝你nifr。然而,這樣一來,Subscription類必須事先知道每個可能的實體,因爲它們必須放在DiscriminatorMap中。這個想法是相反的:創建一個類似插件的架構,以便新實體可以在不修改Subscription類/表的情況下說「你好我是實體'xyz',用戶可以訂閱我」。 –

+0

這可以通過使用偵聽器來實現,該偵聽器即時創建鑑別器映射,即使用對象的返回字符串來訂閱「getDiscriminatorIdentifier()」方法。找到了我? – nifr

+0

是的,我想我是這樣:)所以我猜Doctrine有一個用於在飛行中操縱鑑別器映射的API。 –