2

ネタバレ: 答えは見つかったと思いますが、100% 確実ではありません ;)

私はこの質問をしばらく見てきましたが、うまく機能させることができません。そこで、関係をテストするためにダミーのエンティティを作成しました。これらは次のとおりです。

  • AProductは多くの可能性がありますCart
  • Cart缶には数個入っていますProduct
  • の順はProductCartposition

製品

<?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;
    }
}

app/console generate:doctrine:entities AcmeDemoBundleエンティティを手動で作成し、 @ORM 注釈を追加して関係を設定し、その後gettersetter__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()期待どおりに機能しないことです。そこで、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の間の関係を削除する場合は、(両側に) OneTwoMany 関係を追加する必要があります。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あなたの3つのエンティティを取りますCart、、CartProducts

Cartone-to-manyとの関係を持つべきですCartProducts

CartProductsmany-to-oneとの関係ProductおよびMany-to-one関連付けを持つ必要がありますCart

したがって、最初に を初期化し、次のようCartに製品を追加します。Cart

すべてのためのProduct

  • 必要なandおよびその他の追加パラメータでaCartProductを初期化します。ProductCart
  • に追加しますCart
于 2013-02-19T04:15:00.830 に答える