2016-11-29 62 views
0

我在數據庫中有三個表格:interest,subscriptionsubscriber。該模式是這樣的:以正確的方式通過公共關係建立關係

Subscribr Database schema

訂閱表中有一到兩個利益和用戶一對多的關係。我希望它如何工作,而且我不確定我是否希望它能夠工作以及它的實際工作是如何排隊的,但它應該是這樣的:a訂戶可以有多個興趣,並且每個興趣可以有多個訂閱者。這將允許我看到訂閱者有哪些興趣,以及哪些興趣已經訂閱。然後,認購僅涉及一名訂戶和一項興趣。我認爲這是它是如何設置的,但我只是做了一些測試,查詢認購表,我得到這個回:

C:\xampp\htdocs\www\public_html\playground\subscribr>php list_subscriptions.php 
[email protected] 
--Magazine 
[email protected] 
--Newsletter 
[email protected] 
--Promotions 
[email protected] 
--Email 
[email protected] 
--Magazine 
[email protected] 
--Promotions 
[email protected] 
--Newsletter 
[email protected] 
--Email 
[email protected] 
--Magazine 
[email protected] 
--Promotions 
[email protected] 
--Email 
[email protected] 
--Magazine 
[email protected] 
--Newsletter 
[email protected] 
--Promotions 
[email protected] 
--Promotions 
[email protected] 
--Newsletter 

我想我期望的結果更是這樣的:

C:\xampp\htdocs\www\public_html\playground\subscribr>php list_subscriptions.php 
[email protected] 
--Magazine 
--Newsletter 
--Promotions 
--Email 
[email protected] 
--Magazine 
--Promotions 
[email protected] 
--Newsletter 
--Email 
[email protected] 
--Magazine 
--Promotions 
--Email 
[email protected] 
--Magazine 
[email protected] 
--Newsletter 
[email protected] 
--Promotions 
[email protected] 
--Promotions 
[email protected] 
--Newsletter 

我如果我通過訂閱者查詢,並獲得他們的興趣(通過訂閱表),那麼會得到這個結果。我使用的ORM,所以代碼要做到這一點是這樣的:

$subscriberRepo = $entityManager->getRepository('Subscribr\Entity\Subscriber'); 
$subscribers = $subscriberRepo->findAll(); 

foreach ($subscribers as $subscriber) { 
    echo sprintf("-%s\n", $subscriber->getEmail()); 
    foreach ($subscriber->getInterests() as $interest) { 
     echo sprintf("--%s\n", $interest->getInterest()->getName()); 
    } 
} 

這樣我就可以得到一個用戶的訂閱,訂閱了利益,採用這種模式,但後來有一個點在保持訂閱表格在哪?還是整個事情需要重新做,做我想做的事情?我喜歡訂閱者和興趣之間的間接關係,因此我想向訂閱表中添加額外的列,如從訂閱者表中刪除is_subscribed,並在訂閱中添加名爲subscription_status的列,這樣該解決方案感覺最乾淨。但是,它也幾乎感覺像一個帶有額外字段的連接表。思考?

+0

訂閱表* *是一個帶有額外字段的連接表。所以呢?這就是你如何表示許多與屬性的二元關係。此外,它是*你如何能夠「獲得訂閱者的訂閱和訂閱的興趣」。 ORM使用它來實現getInterests()。 – philipxy

回答

1

根據您的解釋,您可以正確理解您需要映射的內容。在簡化的方式,你有兩個選擇:

選項1

Subscriber 1 - >ñSubscription
Subscriptionñ< - 1 Interest

這意味着間接:Subscriber N - >ñInterest
看不到?讓代碼更好地看到:

foreach ($subscribers as $subscriber) { 
    echo sprintf("-%s\n", $subscriber->getEmail()); 
    foreach ($subscriber->getSubscriptions() as $subscription) { 
     echo sprintf("--%s\n", $subscription->getInterest()->getName()); 
    } 
} 

編輯

上面的代碼將在你的映射下面的變化工作。此代碼說明:迭代每位訂閱者都有訂閱列表的訂閱者,並且每個訂閱都會引起興趣。

Subscriber.php

/** 
    * @var array 
    * 
    * @ORM\OneToMany(targetEntity="Subscription", mappedBy="subscriber", cascade={"persist", "remove"}, orphanRemoval=TRUE) 
    */ 
    private $subscriptions; 

你應該從Subscriber刪除private $interests;。它不會直接訪問Interest

Subscription.php

/** 
* @var Interest 
* 
* @ORM\ManyToOne(targetEntity="Interest", inversedBy="subscribers") 
* @ORM\JoinColumn(name="interest_id", referencedColumnName="id", nullable=FALSE) 
*/ 
private $interest; 

通知每個Subscription將訪問單個Interest

第一個選項是最適合您的情況。

選項2

你可以刪除Subscription類,並使用其表作爲參考表。並直接地圖:Subscriber n - > n Interest

class Subscriber { 

    /** 
     * @var array 
     * 
     * @ORM\ManyToMany(targetEntity="Interest", cascade={"persist", "remove"}, orphanRemoval=TRUE) 
     * @ORM\JoinTable(name="subscription", 
     *  joinColumns={@ORM\JoinColumn(name="subscriber_id", referencedColumnName="id")}, 
     *  inverseJoinColumns={@ORM\JoinColumn(name="interest_id", referencedColumnName="id")} 
     *  ) 
     */ 
     private $interests; 
} 

在此選項不能使用subscription.interest_date「事業subscription表現在的問題僅僅是一個關係表。關於this question的更多解釋。

+1

根據我發佈的模式,似乎我已經有選項1.或者是有什麼我失蹤......這是完全可能的。 – mrClean

+1

是的。但請注意'Subscriber'訪問'Subscriptions'和每個'Subscription'獲得一個'Interest'。由於選項1代碼與代碼有點不同。我編輯以包含選項1中的映射代碼。 –