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