繁体   English   中英

原则2中的多对多关系

[英]ManytoMany Relationship in Doctrine 2

我最近开始使用Zend Framework 2,现在遇到了Doctrine 2,我现在想将其集成到我的第一个项目中。

我现在有以下情况,即使过了几天,我也找不到解决方案。

我有3张桌子:

广告

advert_id
advert_title
etc

类别

category_id
name
label
etc

advert2category

advert2category_category_id
advert2category_advert_id

一个广告可以位于不同的类别中,并且不同的类别具有不同的广告,因此表Advert2Category(ManytoMany)。

阅读www后,我决定它应该是“多对多双向”的,在广告实体处具有“拥有方”。

不要问我为什么决定这样做,但我仍然不完全了解教义。 无论如何,我创建了3个实体,但我只需要广告和类别实体。

我现在希望发生以下情况。

我单击类别,并希望查看该类别中的文章列表。这意味着我必须读出表advert2category。 我创建了实体,在这里是我的广告实体:

因此,这首先是我的广告实体:

namespace Advert\Entity;

use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;

/**
 * Advert
 *
 * @ORM\Table(name="advert")
 * @ORM\Entity
 */

class Advert
{

    /**
     * @var integer
     *
     * @ORM\Column(name="advert_id", type="integer", nullable=false)
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="IDENTITY")
     */
    private $advertId;


    /**
     * @var string
     *
     * @ORM\Column(name="advert_title", type="string", length=255, nullable=true)
     */
     private $advertTitle;


    /**
    * @ORM\ManyToMany(targetEntity="Category", inversedBy="advertCategory", cascade={"persist"})
    * @ORM\JoinTable(name="advert2category",
    * joinColumns={@ORM\JoinColumn(name="advert2category_category_id", referencedColumnName="category_id")},
    * inverseJoinColumns={@ORM\JoinColumn(name="advert2category_advert_id", referencedColumnName="advert_id")}
    * )
    */

    protected $category;

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


    /**
     * Get advertId
     *
     * @return integer 
     */
    public function getAdvertId()
    {
        return $this->advertId;
    }


    /**
     * Set advertTitle
     *
     * @param string $advertTitle
     * @return Advert
     */
    public function setAdvertTitle($advertTitle)
    {
        $this->advertTitle = $advertTitle;

        return $this;
    }

    /**
     * Get advertTitle
     *
     * @return string 
     */
    public function getAdvertTitle()
    {
        return $this->advertTitle;
    }


    /**
     * Set category
     *
     * @param \Advert\Entity\User $category
     * @return Advert
     */
    public function setCategory(\Advert\Entity\Category $category = null)
    {
        $this->category = $category;

        return $this;
    }

    /**
     * Get category
     *
     * @return \Advert\Entity\Category
     */
    public function getCategory()
    {
        return $this->category;
    }
}  

和我的类别实体:

namespace Advert\Entity;

use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;

/**
 * Category
 *
 * @ORM\Table(name="category")
 * @ORM\Entity
 */

class Category
{

    /**
     * @var integer
     *
     * @ORM\Column(name="category_id", type="integer", nullable=false)
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="IDENTITY")
     */
    private $categoryId;

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



    /**
     * @ORM\ManyToMany(targetEntity="Advert", mappedBy="category")
     **/
    private $advertCategory;

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


    /**
     * Get categoryId
     *
     * @return integer 
     */
    public function getCategoryId()
    {
        return $this->categoryId;
    }


    /**
     * Set name
     *
     * @param string $name
     * @return Category
     */
    public function setName($name)
    {
        $this->name = $name;

        return $this;
    }

    /**
     * Get name
     *
     * @return string 
     */
    public function getName()
    {
        return $this->name;
    }
}  

作为第一次测试,我现在在控制器中尝试了以下操作:

//下面的控制器现在可以回显类别ArrayCollection

$data = $this->getEntityManager()->getRepository('Advert\Entity\Advert')->findAll();

foreach($data as $key=>$row)
{

  echo $row->getAdvertTitle();
  echo $row->getUser()->getUsername();
  $categories = $row->getCategory();

  foreach($categories as $row2) {
    echo $row2->getName();
 }

我在这里做错了什么? 谁能给我建议? 提前非常感谢您!

老实说,这是一件非常诚实和美好的事情,这会使您要做的事情变得过于复杂,但仅限于特定领域。

如果您使用Composer包含了Doctrine(推荐的方式),还包括symfony/console ,那么您会得到一堆很棒的工具,可以帮助您完成任务。 有一个非常具体的命令将使您$ doctrine orm:schema-tool:update --force --dump-sql$ doctrine orm:schema-tool:update --force --dump-sql 这将使Doctrine在您的实体中运行(您只需要这两个实体),并将生成表,甚至为您设置*To*关联。 ManyToOne的情况下,它将生成适当的外键架构。 ManyToMany的情况下,它将自动创建并管理自己的关联表,您只需要担心在Entity中为表指定名称。

我不是在开玩笑,这样做。 这将使您的生活值得生活。

至于您的实体设置,这就是您所需要的:

<?php 

namespace Advert\Entity;

use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;

/**
 * Advert
 *
 * @ORM\Table(name="advert")
 * @ORM\Entity
 */

class Advert
{

    /**
     * @var integer
     *
     * @ORM\Column(name="advert_id", type="integer", nullable=false)
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="IDENTITY")
     */
    private $advertId;


    /**
     * @var string
     *
     * @ORM\Column(name="advert_title", type="string", length=255, nullable=true)
     */
     private $advertTitle;


    /**
    * @ORM\ManyToMany(targetEntity="Category", cascade={"persist"})
    * @JoinTable(name="advert_categories")
    */
    protected $category;


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


    /**
     * Get advertId
     *
     * @return integer 
     */
    public function getAdvertId()
    {
        return $this->advertId;
    }


    /**
     * Set advertTitle
     *
     * @param string $advertTitle
     * @return Advert
     */
    public function setAdvertTitle($advertTitle)
    {
        $this->advertTitle = $advertTitle;

        return $this;
    }

    /**
     * Get advertTitle
     *
     * @return string 
     */
    public function getAdvertTitle()
    {
        return $this->advertTitle;
    }


    /**
     * Set category
     *
     * @param ArrayCollection $category
     * @return Advert
     */
    public function setCategory(ArrayCollection $category)
    {
        $this->category = $category;

        return $this;
    }

    /**
     * Get category
     *
     * @return ArrayCollection
     */
    public function getCategory()
    {
        return $this->category;
    }
}  

请注意,getter和setter已记录到Set和Return ArrayCollection ,这对于读取PHPDoc和Annotations的IDE和工具以了解深入的PHP类映射如何工作非常重要。

另外,请注意ManyToMany声明要简单多少? @JoinTable批注在那里为该原则将生成和管理的表命名。 这就是您所需要的!

但是现在,您可能应该从类别实体中删除$advertCategory属性。 Doctrine将使用实体关联映射自动将属性中的嵌入实体水化。

这也有潜在的危险,因为它可能导致无限递归。 基本上,如果您所请求的只是一个ID为1的广告,它将进入并找到与广告1相关的所有类别实体,但是在这些类别中,它会重新引用广告1,Doctrine将对该子广告进行子查询并inject,它将包含一个Category关联,然后将抓取这些类别,依此类推,依次类推,直到PHP由于内存不足而杀死自己。

一旦一切顺利,并且您获得了与“广告”关联的一些“类别”,则在“广告”实体中对类别使用Getter将返回“类别实体”数组。 只需遍历它们:

foreach($category as $advert->getCategories()) {
   echo $category->getName();
}

要么

echo current($advert->getCategories())->getName();

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM