剧透:我想我找到了答案,但我不是百分百肯定;)
我一直在看这个question一段时间,但我无法让它发挥作用。所以我创建了虚拟实体以测试关系,这里是:
Product
可以包含多个Cart
Cart
可以包含多个Product
Product
中的Cart
按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
和{{1} }
现在我是一个控制器,我必须遵循以下代码:
__construct
这样做我出现以下错误:
在关联Acme \ DemoBundle \ Entity \ Cart#cartProducts上找到Acme \ DemoBundle \ Entity \ Product类型的实体,但期待Acme \ DemoBundle \ Entity \ CartHasProduct
所以我的问题是如何将产品添加到购物车中?我是否需要手动创建关系对象(<?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');
}
}
)?我认为Doctrine会做到这一点。我在Doctrine文档中到处查看,我找不到与额外字段关系的例子。
我也调查了供应商的测试,有很多模型(非常有趣),但关系中没有额外的字段。
我在想这样在Cart中创建我自己的方法:
CartHasProduct
但我想知道我是否需要实施它,或者它是否意味着要自动处理?
#### 更新1 ####
所以我最后添加了这个方法public function addProduct(Product $product, $position=0) {
$relation = new CartHasProduct($this, $product, $position);
if (!$this->cartProducts->contains($relation)) {
$this->cartProducts->add($relation);
}
}
。问题是addProduct
没有按预期工作。因此,我尝试从contains()
中删除所有Product
并添加新的Cart
。
以下是我删除产品的功能:
/**
* 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我发现问题是什么,如果要删除2个主要实体(orphanRemoval=true
和{{1}之间的关系,则需要在OneTwoMany关系中添加Cart
(两侧) }}):
Product
并且
/**
* @ORM\Entity
* @ORM\Table(name="demo_product")
*/
class Product
{
...
/**
* @ORM\OneToMany(targetEntity="CartHasProduct", mappedBy="product", cascade={"persist", "remove"}, orphanRemoval=true)
*/
protected $productCarts;
干杯,
马克西姆
答案 0 :(得分:2)
通过使用第三个中间实体,可以实现与额外参数的多对多关联。您有正确的方法,但定义了错误的关联。这是它应该如何。
将您的3个实体Product
,Cart
,CartProducts
Cart
应与one-to-many
CartProducts
关系
CartProducts
应与many-to-one
建立Product
关联,Many-to-one
与Cart
建立关联
首先初始化Cart
,并将产品添加到Cart
,如下所示:
每Product
CartProduct
和Product
以及您需要的其他额外参数初始化Cart
。Cart