2012-01-09 138 views
5

我有实体BasketBasketItem如何坚持一个对象有许多相关对象

/** 
* 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(); 

然后我试图更紧密地跟随manual

$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_idNULL

任何人都可以解释我做错了吗?请注意,我是新来的教条。谢谢!




编辑

我真的糊涂了。这里是我的简单测试:

<?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 )。

+0

灿你发布你的addItem函数的内容?它在内部调用$ this-> items-> add($ item); ?其余的看起来没问题.. – 2012-01-10 07:18:54

+0

@ Kees Schepers,谢谢你的回复!我已经添加了方法'addItem'(和'find')。如果其余的都没问题,我真的迷失了 - 还有什么想法可以尝试? – Czechnology 2012-01-10 11:41:22

+0

前段时间我有一些类似的问题,你是否可以在你的BasketItem类中指定你的字段$ order_id?因为这可能会导致这些问题。如果你怀疑你可以发布你的整个basketitem实体类。我的朋友已经与我博客了这一点:http://pietervogelaar.nl/doctrine-2-use-foreign-key-as-field-in-dql/ – 2012-01-10 11:49:24

回答

3

如果我理解正确的系统,我也有 - 因为它是一个双向的关系 - 手动父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'); 
} 

它正常工作,但如果我以错误的方式,请纠正我。

感谢大家花时间看我的问题!

+0

Yhis是正确的。然而,你应该让自己容易一些,并将篮子与篮子实体的'addItem'方法相关联。 Kees Schepers在上面指出了这一点。这是正确的事情(因为它意味着你永远不会'忘记'在你的控制器中执行它) – calumbrodie 2012-01-11 00:39:30

+0

@kissmyface,是的,这就是我做到这一点的原因(以上只是我工作的第一个版本)。如果我正确地理解了他,凯斯只是问我是否将它添加到项目集合中。这就是我认为的就够了... – Czechnology 2012-01-11 11:03:56

3

您的Basket实体中的注释映射错误:“mappedBy”属性必须引用实体字段,而不是数据库列。

/** 
* @ORM\OneToMany(targetEntity="BasketItem", mappedBy="basket",cascade={"all"}) 
*/ 
protected $items; 
+0

谢谢,我已经修改过,但仍然无效 - 'order_id'列保持'NULL'。 – Czechnology 2012-01-10 14:03:02

+0

BasketItem的构造函数是什么?你能发布其内容吗? – AlterPHP 2012-01-10 14:35:16

+0

我已经编辑了一个简单的例子,它是1:1我做的。我不明白为什么它仍然失败。 – Czechnology 2012-01-10 14:52:44

1

我是Symfony和Doctrine的新手,但这很奇怪。我因子评分,它应该是双向的,但似乎u必须设置篮子BasketItem

$bi->setBasket($basket); 

如果u想使它的工作两者兼得,例如:

$basket->addItem($bi); 

u必须修改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); 
} 

[编辑]看看这个:http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/association-mapping.html#owning-and-inverse-side-on-a-manytomany-association