[英]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.