我有实体Basket
和BasketItem
:
/**
* Acme'BasketBundle'Entity'Basket
*
* @ORM'Entity(repositoryClass="Acme'BasketBundle'Repository'BasketRepository")
* @ORM'Table(name="orders")
* @ORM'HasLifecycleCallbacks()
*/
class Basket
{
/**
* @var integer $id
*
* @ORM'Column(name="id", type="integer")
* @ORM'Id
* @ORM'GeneratedValue(strategy="AUTO")
*/
private $id;
// ...
/**
* @ORM'OneToMany(targetEntity="BasketItem", mappedBy="order_id",cascade={"all"})
*/
protected $items;
// ...
public function __construct() {
$this->items = new ArrayCollection();
}
/**
* Add item
*
* @param BasketItem $item
*/
public function addItem(BasketItem $item)
{
$key = $this->find($item->getProduct()->getId());
if ($key === false) {
$this->items->add($item);
} else {
$this->items->get($key)->raiseQuantity($item->getQuantity());
}
}
/**
* Find an item (if present)
*
* @param integer $id
* @return integer
*/
public function find($id)
{
foreach ($this->items as $key => $item) {
if ($item->getProduct()->getId() == $id)
return $key;
}
return false;
}
}
/**
* Acme'BasketBundle'Entity'BasketItem
*
* @ORM'Entity
* @ORM'Table(name="order_items")
*/
class BasketItem
{
/**
* @var integer $id
*
* @ORM'Column(name="id", type="integer")
* @ORM'Id
* @ORM'GeneratedValue(strategy="AUTO")
*/
private $id;
// ...
/**
* @ORM'ManyToOne(targetEntity="Basket", inversedBy="items")
* @ORM'JoinColumn(name="order_id", referencedColumnName="id")
*/
private $basket;
// ...
}
现在,当我创建一个篮子并将其装满项目时,我很难将其持久化到数据库中。
以下操作没有按预期进行。
$basket = new Basket();
$basket->addItem(new BasketItem($product1, 1));
$basket->addItem(new BasketItem($product2, 2));
$em->persist($basket);
$em->flush();
然后我试着更仔细地遵循手册:
$basket = new Basket();
$basket->addItem(new BasketItem($product1, 1));
$basket->addItem(new BasketItem($product2, 2));
$em->persist($basket);
foreach ($basket->getItems() as $item) {
$em->persist($item);
}
$em->flush();
这也没有像预期的那样奏效。
在这两种情况下,所有数据都会保存到数据库,但购物篮项目与购物篮无关,即BasketItem
实体的order_id
是NULL
。
有人能解释一下我做错了什么吗?请注意,我是新的学说。谢谢
编辑:
我已经很困惑了。这是我的简化测试:
<?php
namespace Amsel'BasketBundle'Entity;
use Doctrine'ORM'Mapping as ORM;
use Doctrine'Common'Collections'ArrayCollection;
/**
* Amsel'BasketBundle'Entity'Basket
*
* @ORM'Entity(repositoryClass="Amsel'BasketBundle'Repository'BasketRepository")
* @ORM'Table(name="orders")
*/
class Basket
{
/**
* @var integer $id
*
* @ORM'Column(name="id", type="integer")
* @ORM'Id
* @ORM'GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* @var ArrayCollection $items
*
* @ORM'OneToMany(targetEntity="BasketItem", mappedBy="basket", cascade={"all"})
*/
protected $items;
public function __construct() {
$this->items = new ArrayCollection();
}
/**
* Add item
*
* @param BasketItem $item
*/
public function addItem(BasketItem $item)
{
$this->items->add($item);
}
/**
* Get id
*
* @return integer
*/
public function getId()
{
return $this->id;
}
/**
* Get items
*
* @return Doctrine'Common'Collections'Collection
*/
public function getItems()
{
return $this->items;
}
}
<?php
namespace Amsel'BasketBundle'Entity;
use Doctrine'ORM'Mapping as ORM;
/**
* Amsel'BasketBundle'Entity'BasketItem
*
* @ORM'Entity(repositoryClass="Amsel'BasketBundle'Repository'BasketItemRepository")
* @ORM'Table(name="order_items")
*/
class BasketItem
{
/**
* @var integer $id
*
* @ORM'Column(name="id", type="integer")
* @ORM'Id
* @ORM'GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* @var Basket $basket
*
* @ORM'ManyToOne(targetEntity="Basket", inversedBy="items")
* @ORM'JoinColumn(name="order_id", referencedColumnName="id")
*/
protected $basket;
/**
* Get id
*
* @return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set basket
*
* @param Amsel'BasketBundle'Entity'Basket $basket
*/
public function setBasket('Amsel'BasketBundle'Entity'Basket $basket)
{
$this->basket = $basket;
}
/**
* Get basket
*
* @return Amsel'BasketBundle'Entity'Basket
*/
public function getBasket()
{
return $this->basket;
}
}
public function testAction(Request $request) {
$em = $this->getDoctrine()->getEntityManager();
$basket = new Basket();
$basket->addItem(new BasketItem());
$basket->addItem(new BasketItem());
$em->persist($basket);
try {
$em->flush();
} catch(Exception $e) {
die('ERROR: '.$e->getMessage());
}
die ('end');
}
但仍然-订单项(BasketItem
)已存储,但未链接到订单(Basket
)。
Basket实体中的注释映射错误:"mappedBy"属性必须引用实体字段,而不是数据库列。
/**
* @ORM'OneToMany(targetEntity="BasketItem", mappedBy="basket",cascade={"all"})
*/
protected $items;
如果我正确理解系统,我还必须手动将父Basket
实体分配给每个BasketItem
实体,因为这是一个双向关系。
public function testAction(Request $request) {
$em = $this->getDoctrine()->getEntityManager();
$basket = new Basket();
$bi1 = new BasketItem();
$bi1->setBasket($basket);
$bi2 = new BasketItem();
$bi2->setBasket($basket);
$basket->addItem($bi1);
$basket->addItem($bi2);
$em->persist($basket);
try {
$em->flush();
} catch(Exception $e) {
die('ERROR: '.$e->getMessage());
}
die ('end');
}
这样做很好,但如果我走错了路,请纠正我。
感谢所有花时间研究我问题的人!
我是Symfony and Doctrine的新手,但这很奇怪。我认为它应该双向工作,但似乎你必须在BasketItem 上设置Basket
$bi->setBasket($basket);
如果你想让它双向工作,例如:
$basket->addItem($bi);
你必须修改你的addItem方法和removeItem方法
/**
* Add item
*
* @param BasketItem $item
*/
public function addItem(BasketItem $item)
{
$item->setBasket($this);
$this->items->add($item);
}
/**
* Remove item
*
* @param BasketItem $item
*/
public function removeItem(BasketItem $item)
{
$item->setBasket(null);
$this->items->removeElement($item);
}
[EDIT]如下所示:http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/association-mapping.html#owning-和多人对多人关联