2

剧透:我想我找到了答案,但我不是 100% 确定;)

我一直在研究这个问题一段时间,但我无法让它发挥作用。所以我创建了虚拟实体来测试关系,它们是:

  • AProduct可以在很多Cart
  • 一个Cart罐头包含几个Product
  • Productin aCart是按 a 排序的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\Entity\Cart#cartProducts 上找到类型为 Acme\DemoBundle\Entity\Product 的实体,但期待 Acme\DemoBundle\Entity\CartHasProduct

所以我的问题是如何将产品添加到购物车中?我是否需要手动创建关系对象 ( CartHasProduct)?我认为 Doctrine 会做到的。我到处查看 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。问题是它contains()没有按预期工作。所以我试图从中删除所有ProductCart添加一个新的。

这是我删除产品的功能:

/**
 * 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=trueOneTwoMany 关系(在两侧):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();
    }

干杯,

马克西姆

4

1 回答 1

2

可以通过使用第三个中间实体来实现与额外参数的多对多关联。您有正确的方法,但定义了错误的关联。应该是这样的。

以您的 3 个实体Product, Cart,CartProducts

Cart应该有one-to-many关系CartProducts

CartProducts应该many-to-oneProduct_ Many-to-one_Cart

所以你首先初始化 a Cart,然后Cart像这样添加产品:

对于每一个Product

  • CartProduct使用您需要的ProductandCart和其他额外参数初始化 a 。
  • 将其添加到Cart
于 2013-02-19T04:15:00.830 回答