ネタバレ: 答えは見つかったと思いますが、100% 確実ではありません ;)
私はこの質問をしばらく見てきましたが、うまく機能させることができません。そこで、関係をテストするためにダミーのエンティティを作成しました。これらは次のとおりです。
- A
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;
}
}
app/console generate:doctrine:entities AcmeDemoBundle
エンティティを手動で作成し、 @ORM 注釈を追加して関係を設定し、その後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()
期待どおりに機能しないことです。そこで、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 関係を追加する必要があります。Cart
Product
/**
* @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();
}
乾杯、
マキシム