I have entities Basket
and 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;
// ...
}
Now when I create a basket and fill it with items, I have trouble persisting it into the db.
Following doesn't work as expected.
$basket = new Basket();
$basket->addItem(new BasketItem($product1, 1));
$basket->addItem(new BasketItem($product2, 2));
$em->persist($basket);
$em->flush();
Then I tried following the manual more closely:
$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();
That didn't work as expected neither.
In both cases all the data gets saved to the database but the basket items are not related to the basket, i.e. order_id
of the BasketItem
entity is NULL
.
Can anyone explain me what I'm doing wrong, please? Please note I'm new to Doctrine. Thanks!
EDIT:
I'm really confused already. Here's my simplified test:
<?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');
}
But still - the order items (BasketItem
) get stored but are not linked to the order (Basket
).
Your annotation mapping is wrong in your Basket entity : the "mappedBy" attribute must refers to an entity field, not to a database column.
/**
* @ORM\OneToMany(targetEntity="BasketItem", mappedBy="basket",cascade={"all"})
*/
protected $items;
If I understand the system correctly, I also have to - because it is a bidirectional relation - manually assign the parent Basket
entity to every BasketItem
entity.
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');
}
It works fine like this but if I'm going in a wrong way, please correct me.
Thanks to everyone who took the time to look at my question!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With