2012-01-09 8 views
5

私は、エンティティBasketBasketItemを持って一つのオブジェクトを永続化しますそれをdbに永続化させるのに問題があります。どのように多くの関連オブジェクト

以下は、期待どおりに動作しません。

$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あります。

誰でも私が間違っていることを説明できますか?私はDoctrineを初めて使うことに注意してください。ありがとう!




EDIT

私はすでに本当に混乱しています。ここに私の簡素化テストです:まだ

<?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)を呼び出しますか? ?残りは大丈夫です。 –

+0

@Kees Schepers、あなたの返信をありがとう!私は 'addItem'(および' find')メソッドを追加しました。残りの部分が大丈夫なら、私は本当に迷っています。 – Czechnology

+0

私は少し前にsimular問題を抱えていましたが、BasketItemクラスのフィールド$ order_idをおそらく指定していますか?これらの問題が発生する可能性があります。あなたがあなたのバスケットアイテムのエンティティクラス全体を投稿することができないのであれば疑問です。私の友人は私とこのことについてブログしてきました:http://pietervogelaar.nl/doctrine-2-use-foreign-key-as-field-in-dql/ –

答えて

3

私はシステムを正しく理解していれば、私はまたしなければならない - それは双方向の関係であるので - 手動ですべてのBasketItemエンティティに親Basketエンティティを割り当てます。

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

これは正しいです。しかし、あなたは自分でそれを簡単にし、バスケットのアイテムの_inside_ 'addItem'メソッドにバスケットを関連付ける必要があります。 Kees Schepersはこれを上に指摘しました。 – calumbrodie

+0

@kissmyface、ええ、これが私のやり方です(上記は私が働いている最初のバージョンです)。これは正しいことです。私が彼を正しく理解していれば、Keesはそれをアイテムコレクションに追加するかどうか尋ねました。そしてそれは私が十分だと思ったことです... – Czechnology

3

あなたの注釈マッピングがあなたのバスケットエンティティで間違っています:「mappedBy」属性は、データベース列ではなくエンティティフィールドを参照する必要があります。

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

ありがとう、私はそれを修正しましたが、それでも動作しません - 'order_id'列は' NULL'のままです。 – Czechnology

+0

BasketItemコンストラクタとは何ですか?あなたはそのコンテンツを投稿できますか? – AlterPHP

+0

私は1:1の簡単な例で編集しました。なぜまだ失敗するのか分かりません。 – Czechnology

1

私はSymfonyとDoctrineで新しいですが、これは変です。私はそれが両方の方法を動作する必要があることを取り払わが、uはuはそれは両方の方法などを操作できるようにしたい場合はBasketItem

$bi->setBasket($basket); 

をバスケットを設定する必要がいるようです:

$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); 
} 

[EDIT]これを見て:http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/association-mapping.html#owning-and-inverse-side-on-a-manytomany-association

関連する問題