2

擾流:我想我找到了答案,但我不是100%確定;)Doctrine2:許多一對多在參考表的額外列(添加記錄)

我一直在尋找這question一段時間,但我無法設法使其工作。所以我創建實體假人測試的關係,在這裏,他們是:

  • 一個Product可以在許多Cart
  • 一個Cart可以包含幾個Product
  • CartProduct是由訂單position

產品

<?php 

namespace Acme\DemoBundle\Entity; 

use Doctrine\ORM\Mapping as ORM; 
use Doctrine\Common\Collections\ArrayCollection; 
use Symfony\Component\Validator\Constraints as Assert; 

/** 
* @ORM\Entity 
* @ORM\Table(name="demo_product") 
*/ 
class Product 
{ 
    /** 
    * @ORM\Id 
    * @ORM\Column(type="integer") 
    * @ORM\GeneratedValue(strategy="AUTO") 
    */ 
    protected $id; 

    /** 
    * @ORM\OneToMany(targetEntity="CartHasProduct", mappedBy="product", cascade={"all"}) 
    */ 
    protected $productCarts; 

    /** 
    * Constructor 
    */ 
    public function __construct() 
    { 
     $this->productCarts = new \Doctrine\Common\Collections\ArrayCollection(); 
    } 

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

    /** 
    * Add productCarts 
    * 
    * @param \Acme\DemoBundle\Entity\CartHasProduct $productCarts 
    * @return Product 
    */ 
    public function addProductCart(\Acme\DemoBundle\Entity\CartHasProduct $productCarts) 
    { 
     $this->productCarts[] = $productCarts; 

     return $this; 
    } 

    /** 
    * Remove productCarts 
    * 
    * @param \Acme\DemoBundle\Entity\CartHasProduct $productCarts 
    */ 
    public function removeProductCart(\Acme\DemoBundle\Entity\CartHasProduct $productCarts) 
    { 
     $this->productCarts->removeElement($productCarts); 
    } 

    /** 
    * Get productCarts 
    * 
    * @return \Doctrine\Common\Collections\Collection 
    */ 
    public function getProductCarts() 
    { 
     return $this->productCarts; 
    } 
} 

<?php 

namespace Acme\DemoBundle\Entity; 

use Doctrine\ORM\Mapping as ORM; 
use Doctrine\Common\Collections\ArrayCollection; 
use Symfony\Component\Validator\Constraints as Assert; 

/** 
* @ORM\Entity 
* @ORM\Table(name="demo_cart") 
*/ 
class Cart 
{ 
    /** 
    * @ORM\Id 
    * @ORM\Column(type="integer") 
    * @ORM\GeneratedValue(strategy="AUTO") 
    */ 
    protected $id; 

    /** 
    * @ORM\OneToMany(targetEntity="CartHasProduct", mappedBy="cart", cascade={"all"}) 
    */ 
    protected $cartProducts; 

    /** 
    * Constructor 
    */ 
    public function __construct() 
    { 
     $this->cartProducts = new \Doctrine\Common\Collections\ArrayCollection(); 
    } 

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

    /** 
    * Add cartProducts 
    * 
    * @param \Acme\DemoBundle\Entity\CartHasProduct $cartProducts 
    * @return Cart 
    */ 
    public function addCartProduct(\Acme\DemoBundle\Entity\CartHasProduct $cartProducts) 
    { 
     $this->cartProducts[] = $cartProducts; 

     return $this; 
    } 

    /** 
    * Remove cartProducts 
    * 
    * @param \Acme\DemoBundle\Entity\CartHasProduct $cartProducts 
    */ 
    public function removeCartProduct(\Acme\DemoBundle\Entity\CartHasProduct $cartProducts) 
    { 
     $this->cartProducts->removeElement($cartProducts); 
    } 

    /** 
    * Get cartProducts 
    * 
    * @return \Doctrine\Common\Collections\Collection 
    */ 
    public function getCartProducts() 
    { 
     return $this->cartProducts; 
    } 
} 

最後CartHasProduct參考表

<?php 

namespace Acme\DemoBundle\Entity; 

use Doctrine\ORM\Mapping as ORM; 
use Doctrine\Common\Collections\ArrayCollection; 
use Symfony\Component\Validator\Constraints as Assert; 

/** 
* @ORM\Entity 
* @ORM\Table(name="demo_cartHasProduct") 
*/ 
class CartHasProduct 
{ 
    /** 
    * @ORM\Id 
    * @ORM\Column(type="integer") 
    * @ORM\GeneratedValue(strategy="AUTO") 
    */ 
    protected $id; 

    /** 
    * @ORM\ManyToOne(targetEntity="Cart", inversedBy="productCarts") 
    */ 
    protected $cart; 

    /** 
    * @ORM\ManyToOne(targetEntity="Product", inversedBy="cartProducts") 
    */ 
    protected $product; 

    /** 
    * @ORM\Column(type="integer") 
    */ 
    protected $position; 

    public function __construct(Cart $cart, Product $product, $position=0) { 
     $this->cart = $cart; 
     $this->product = $product; 
     $this->setPosition($position); 
    } 

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

    /** 
    * Set position 
    * 
    * @param integer $position 
    * @return CartHasProduct 
    */ 
    public function setPosition($position) 
    { 
     $this->position = $position; 

     return $this; 
    } 

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

    /** 
    * Set cart 
    * 
    * @param \Acme\DemoBundle\Entity\Cart $cart 
    * @return CartHasProduct 
    */ 
    public function setCart(\Acme\DemoBundle\Entity\Cart $cart = null) 
    { 
     $this->cart = $cart; 

     return $this; 
    } 

    /** 
    * Get cart 
    * 
    * @return \Acme\DemoBundle\Entity\Cart 
    */ 
    public function getCart() 
    { 
     return $this->cart; 
    } 

    /** 
    * Set product 
    * 
    * @param \Acme\DemoBundle\Entity\Product $product 
    * @return CartHasProduct 
    */ 
    public function setProduct(\Acme\DemoBundle\Entity\Product $product = null) 
    { 
     $this->product = $product; 

     return $this; 
    } 

    /** 
    * Get product 
    * 
    * @return \Acme\DemoBundle\Entity\Product 
    */ 
    public function getProduct() 
    { 
     return $this->product; 
    } 
} 

我已經手動創建該實體,加入@ORM註釋設置的關係,那麼我已使用app/console generate:doctrine:entities AcmeDemoBundle來填充getter,setter__construct

現在我控制器我有以下代碼:

<?php 

namespace Acme\DemoBundle\Controller; 

use Symfony\Bundle\FrameworkBundle\Controller\Controller; 

class WelcomeController extends Controller 
{ 
    public function indexAction() 
    { 
     // Create a Cart Entity 
     $cart = new \Acme\DemoBundle\Entity\Cart(); 

     // Create a Product Entity 
     $product = new \Acme\DemoBundle\Entity\Product(); 

     // Add the Product into the Cart 
     $cart->getCartProducts()->add($product); 

     // Save the Cart 
     $em = $this->getDoctrine()->getManager(); 
     $em->persist($cart); 
     $em->flush(); 

     return $this->render('AcmeDemoBundle:Welcome:index.html.twig'); 
    } 
} 

這樣做,我有以下的錯誤來了:

的關聯類型的Acme \ DemoBundle \實體\產品的

找到實體ACME \ DemoBundle \實體\車#cartProducts,但期待的Acme \ DemoBundle \實體\ CartHasProduct

所以我的問題是如何增加一個產品成車?我是否需要手動創建關係對象(CartHasProduct)?我會認爲主義會做到這一點。我到處看到Doctrine文檔,並且找不到與額外領域有關係的例子。

我也看過供應商的測試,有很多模型(非常有趣),但沒有關係中的額外領域。

我想在車中創造我自己的方法是這樣的:

public function addProduct(Product $product, $position=0) { 
    $relation = new CartHasProduct($this, $product, $position); 
    if (!$this->cartProducts->contains($relation)) { 
     $this->cartProducts->add($relation); 
    } 
} 

,但我想還是知道如果我需要實現它,如果它的意思是自動處理?

#### 更新1 ####

所以我最終將這種方法addProduct。問題是未按預期工作。所以我試圖從Cart中刪除所有Product並添加一個新的。

這裏是我的功能刪除產品:

/** 
* Reset the product for the cart 
* 
* @return bool 
*/ 
public function resetCart() { 
    foreach ($this->getCartProducts() as $relation) { 
     $relation->getProduct()->removeProductCart($relation); 
     $this->removeCartProducts($relation); 
    } 
} 

,這裏是我怎麼稱呼它:

$em = $this->getDoctrine()->getManager(); 
    $cart->resetCart(); 
    $em->persist($cart); 
    $em->flush(); 

但記錄中沒有CartHasProduct表中刪除。

更新2

我發現是什麼問題,你需要在OneTwoMany關係添加orphanRemoval=true(在兩側),如果你想刪除的2個主要的實體之間(CartProduct)的關係:

/** 
* @ORM\Entity 
* @ORM\Table(name="demo_product") 
*/ 
class Product 
{ 
... 

    /** 
    * @ORM\OneToMany(targetEntity="CartHasProduct", mappedBy="product", cascade={"persist", "remove"}, orphanRemoval=true) 
    */ 
    protected $productCarts; 

而且

/** 
* @ORM\Entity 
* @ORM\Table(name="demo_cart") 
*/ 
class Cart 
{ 
    ... 

    /** 
    * @ORM\OneToMany(targetEntity="CartHasProduct", mappedBy="cart", cascade={"persist", "remove"}, orphanRemoval=true) 
    */ 
    protected $cartProducts; 

    ... 

    /** 
    * Reset the product for the cart 
    */ 
    public function resetCart() { 
     $this->getCartProducts()->clear(); 
    } 

乾杯,

Maxime

回答

2

很多很多與額外參數的關聯可以通過使用第三個中間實體來實現。您有正確的方法,但定義了錯誤的關聯。這是它應該如何。

以你的3個實體ProductCartCartProducts

Cart應該有CartProducts

CartProducts一個one-to-many關係應該有many-to-one關係ProductCart

Many-to-one協會因此你首先初始化Cart,並將產品添加到Cart像這樣:

Product

  • 初始化CartProduct與您需要的ProductCart和其他額外的參數。
  • 加入購物車Cart
相關問題