首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >以正确的方式通过公共表格建立关系

以正确的方式通过公共表格建立关系
EN

Stack Overflow用户
提问于 2016-11-29 20:46:31
回答 1查看 78关注 0票数 0

数据库中有三个表:interestsubscriptionsubscriber。模式如下所示:

订阅表对兴趣和订阅者都有一对多的关系。我希望它如何工作,我也不知道我是否想让它工作,它是如何工作的,但是它应该是这样的:订阅者可以有多个兴趣,每个兴趣可以有多个订阅者。这样,我便可以看到订阅者有哪些兴趣,有哪些兴趣。然后,订阅只涉及到一个订阅者和一个兴趣。--我认为这就是它的设置方式--但是我只是做了一些查询订阅表的测试,并得到了如下结果:

代码语言:javascript
复制
C:\xampp\htdocs\www\public_html\playground\subscribr>php list_subscriptions.php
-testemail@tester.com
--Magazine
-testemail@tester.com
--Newsletter
-testemail@tester.com
--Promotions
-testemail@tester.com
--Email
-testemail2@tester.com
--Magazine
-testemail2@tester.com
--Promotions
-testemail3@tester.com
--Newsletter
-testemail3@tester.com
--Email
-testemail4@tester.com
--Magazine
-testemail4@tester.com
--Promotions
-testemail4@tester.com
--Email
-testemail5@tester.com
--Magazine
-testemail6@tester.com
--Newsletter
-testemail7@tester.com
--Promotions
-testemail9@tester.com
--Promotions
-testemail10@tester.com
--Newsletter 

我想我期望的结果会是这样的:

代码语言:javascript
复制
C:\xampp\htdocs\www\public_html\playground\subscribr>php list_subscriptions.php
-testemail@tester.com
--Magazine
--Newsletter
--Promotions
--Email
-testemail2@tester.com
--Magazine
--Promotions
-testemail3@tester.com
--Newsletter
--Email
-testemail4@tester.com
--Magazine
--Promotions
--Email
-testemail5@tester.com
--Magazine
-testemail6@tester.com
--Newsletter
-testemail7@tester.com
--Promotions
-testemail9@tester.com
--Promotions
-testemail10@tester.com
--Newsletter

如果我通过订阅者查询并获取他们的兴趣(通过订阅表),我就会得到这个结果。我正在使用ORM,所以这样做的代码如下:

代码语言:javascript
复制
$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的列,这种解决方案感觉是最干净的。但是,它也几乎像一个带有额外字段的联接表。有什么想法?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2016-11-29 22:17:04

根据您的解释,a可以正确地理解您需要映射什么。以一种简化的方式,您有两个选项:

选项1

Subscriber 1 -> n Subscription

Subscription n <- 1 Interest

它的间接意思是:Subscriber n -> n Interest

没看见吗?让代码看得更清楚:

代码语言:javascript
复制
foreach ($subscribers as $subscriber) {
   echo sprintf( "-%s\n", $subscriber->getEmail() );
   foreach ($subscriber->getSubscriptions() as $subscription) {
      echo sprintf( "--%s\n", $subscription->getInterest()->getName() );
   }
}

编辑

上面的代码将适用于映射中的以下更改。此代码说明:迭代订阅服务器,其中每个订阅服务器都有一个订阅列表,每个订阅引用兴趣。

Subscriber.php

代码语言:javascript
复制
 /**
  * @var array
  * 
  * @ORM\OneToMany(targetEntity="Subscription", mappedBy="subscriber",    cascade={"persist", "remove"}, orphanRemoval=TRUE)
  */
  private $subscriptions;

您应该从private $interests;中删除Subscriber。它不会直接访问Interest

Subscription.php

代码语言:javascript
复制
/**
 * @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

代码语言:javascript
复制
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
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/40875478

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档