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
相关问题