簡體   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