【问题标题】:Doctrine - ManyToMany教义 - 多对多
【发布时间】:2019-06-23 12:08:25
【问题描述】:

我真的希望有人能帮我解决这个问题,因为它让我发疯,这应该很简单

数据库表示例(ID 是所有表的主列)

Exhibitors
id  |   name       |   address_line_1
3   |  Test Name   |   Test 123 Street
4   |  Test Name 2 |  Test 123 Street 1
5   |  Test Name 3 |  Test 123 Street 2
6   |  Test Name 4 |  Test 123 Street 2

Shows
id  |   name             |  location
7   |  The Greatest Show |   USA
8   |  Super Show        |   London, UK
9   |  A Great Show      |   Toronto, CA
10  |  Fab Show          |  NEC, Birmingham, UK


Links
id  |   show_id  |  exhibitor_id | agent_id | type
1   |       7    |      3        |   null   |  1
1   |       7    |      5        |   null   |  1
1   |       8    |      3        |   null   |  1
1   |       10   |      6        |   null   |  1

现在我正在尝试做的链接是多对多,所以基本上,每个展会可以有多个参展商,反之亦然,每个参展商可以分配到多个展会。当前实体正在创建一个名为 ppShowExhibLinks 的全新表,我真的不希望它这样做,但我真的卡住了......

Links 表将包含不同类型的链接,因此类型和 agent_id,所以不知何故,我试图让关系按照以下方式做一些事情:

$show = new Show(); $show->getExhibitors();

然后执行类似“获取 show_id 为当前节目且类型为 1 的所有链接”

然后反过来

$show = 新参展商(); $show->getShows(); 然后,这会执行类似“获取所有链接,其中 existor_id 是当前参展商并且类型是 1”

PS:我知道该对象的新实例不会有任何链接展览/展示,而只是为了演示该对象。

 Entities

    /**
    * @ORM\Table(name="ppShows")
    * @ORM\Entity(repositoryClass="App\Repository\ShowRepository")
    */
    class Show
    {
    /**
     * @ORM\Id()
     * @ORM\GeneratedValue()
     * @ORM\Column(type="integer")
     */
    private $id;

    /**
     * @ORM\Column(type="string", length=255, nullable=false)
     */
    protected $name;


    /**
     * @ORM\Column(type="string", length=255, nullable=false)
     */
    protected $location;

   /**
     * @var \Doctrine\Common\Collections\Collection|Exhibitor[]
     *
     * @ORM\ManyToMany(targetEntity="Exhibitor", inversedBy="shows")
     * @ORM\JoinTable(
     *  name="ppShowExhibLinks",
     *  joinColumns={
     *      @ORM\JoinColumn(name="show_id", referencedColumnName="id")
     *  },
     *  inverseJoinColumns={
     *      @ORM\JoinColumn(name="exhibitor_id", referencedColumnName="id")
     *  }
     * )
     */
    protected $exhibitors;



********************************************


class Exhibitor
{
    /**
     * @ORM\Id()
     * @ORM\GeneratedValue()
     * @ORM\Column(type="integer")
     */
    private $id;

    /**
     * @ORM\Column(type="string", length=255, nullable=false)
     */
    protected $name;

    /**
     * @ORM\Column(type="string", length=255, nullable=false)
     */
    protected $address_line_1;

   /**
     * @var \Doctrine\Common\Collections\Collection|Show[]
     *
     * @ORM\ManyToMany(targetEntity="Show", inversedBy="exhibitors")
     * @ORM\JoinTable(
     *  name="ppShowExhibLinks",
     *  joinColumns={
     *      @ORM\JoinColumn(name="show_id", referencedColumnName="id")
     *  },
     *  inverseJoinColumns={
     *      @ORM\JoinColumn(name="exhibitor_id", referencedColumnName="id")
     *  }
     * )
     */
    protected $shows;





class Link
{
    /**
     * @ORM\Id()
     * @ORM\GeneratedValue()
     * @ORM\Column(type="integer")
     */
    private $id;

     /**
     * @ORM\Column(type="integer", options={"default" : 0}, nullable=true)
     */
    protected $show_id;

     /**
     * @ORM\Column(type="integer", options={"default" : 0}, nullable=true)
     */
    protected $exhibitor_id;

    /**
     * @ORM\Column(type="integer", options={"default" : 0}, nullable=true)
     */
    protected $agent_id;

      /**
     * @ORM\Column(type="integer", options={"default" : 1}, nullable=false)
     */
    protected $type;

【问题讨论】:

  • 您是遇到错误还是只是无法正常工作?我已经可以说:当使用多对多时,您应该只在一侧定义@JoinTable,而不是同时定义两者。如此处所述:https://www.doctrine-project.org/projects/doctrine-orm/en/2.6/reference/association-mapping.html#many-to-many-bidirectional
  • 是的,它根本不工作,我发现我很难理解它。
  • 嗨 Lunin,Junction 实体,这让我更加困惑!

标签: php sql symfony doctrine entity-relationship


【解决方案1】:

您必须为ShowExhibitor 表添加与Link 的关系。

显示实体:

    /**
     * One show may have many links
     * @OneToMany(targetEntity="Link", mappedBy="show")
     */
    private $links;
    // ...

    public function __construct() {
        $this->links = new ArrayCollection();
    }

参展实体

    /**
     * One Exhibitor may have many links
     * @OneToMany(targetEntity="Link", mappedBy="exhibitor")
     */
    private $links;
    // ...

    public function __construct() {
        $this->links = new ArrayCollection();
    }

链接实体:

/**
 * Many links have one product.
 * @ManyToOne(targetEntity="Show", inversedBy="links")
 * @JoinColumn(name="show_id", referencedColumnName="id")
 */
private $show;

/**
 * Many links have one exhibitor.
 * @ManyToOne(targetEntity="Exhibitor", inversedBy="links")
 * @JoinColumn(name="exhibitor_id", referencedColumnName="id")
 */
private $exhibitor;

好的,ShowExhibitor 现在通过多对多关系相互关联,并且都通过多对一关系与第三个 Link 实体关联。那可能是您正在寻找的。现在你可以像这样从参展商那里得到所有的节目

$exhibitor->getShows()

反之亦然

$show->getExibitors();

最后,从存储库中获取所有链接

$this->linkRepository->findBy([ "show" => %show_id%, "type" => %type% ]);

【讨论】:

  • 感谢 Lunin,是的,这是有道理的,但是如果 getShows() 和 getExhibitors() 方法不存在于每个实体中,它们如何工作?
  • 你必须手动添加所有的 getter/setter,或者让 Symfony 为你做这件事stackoverflow.com/questions/21317022/…,这取决于你有哪个 Symfony 版本
  • 不要将其视为多对多关系,因为您的链接实体包含其他字段。在这种情况下,您不仅有两个与链接表连接的实体,而且链接表也是一个实体。在您的示例中,链接实体。因此,即实体展览中的 getExhibitors 将为您提供与您的展览相关的所有参展商。要仅获取一些参展商,您将编写自己的 Getter getExhibitorsTypeOne,即获取参展商,然后使用标准过滤它们,即
  • 是的,本杰明说得有道理,但是我该怎么写那个吸气剂,我有点困惑(对不起,我是教义和 symfony 的新手)
  • @JamesPrince 检查我在上面评论中提供的链接,有一个命令会为你生成 getter
猜你喜欢
  • 1970-01-01
  • 2014-01-21
  • 2013-08-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多