2014-02-28 140 views
0

我正在努力設置實體正確的時刻。 Here's情況:學說和ZF2:存儲ManyToOne關係沒有級聯

「國家」有一個或多個「客戶」

從來就與所有國家的國家表,我想保存與每個客戶一個參考的國家。非常簡單並且經常需要。

但我無法正確配置實體。如果我不在「客戶」類中定義級聯方法,則會發生異常。如果我添加一個級聯方法,那麼country對象也會作爲新記錄添加到country表中,但我只想在Customer表中引用此對象。

Customer類

/** 
* @ORM\Entity 
* @ORM\Table(name="PS_Customer") 
*/ 
class Customer { 
/** 
* @ORM\Id 
* @ORM\GeneratedValue(strategy="AUTO") 
* @ORM\Column(type="integer") 
*/ 
protected $id; 

/** 
* @ORM\ManyToOne(targetEntity="Country",inversedBy="id") 
* @ORM\JoinColumn(name="country_id", referencedColumnName="id") 
*/ 
protected $country; 
} 

國家類

/** 
* @ORM\Entity 
* @ORM\Table(name="PS_Country") 
*/ 
class Country { 
    /** 
    * @ORM\Id 
    * @ORM\GeneratedValue(strategy="AUTO") 
    * @ORM\Column(type="integer") 
    * @ORM\OneToMany(targetEntity="Customer", mappedBy="country") 
    */ 
    protected $id; 

    /** @ORM\Column(type="string") */ 
    protected $name; 

    /** @ORM\Column(type="string") */ 
    protected $iso2; 

} 

如果我想存儲的客戶對象與此定義,我收到以下錯誤:

A new entity was found through the relationship 'Photoshop\Entity\Customer#country' that was not configured to cascade persist operations for entity: Photoshop\Entity\[email protected] To solve this issue: Either explicitly call EntityManager#persist() on this unknown entity or configure cascade persist this association in the mapping for example @ManyToOne(..,cascade={"persist"}). If you cannot find out which entity causes the problem implement 'Photoshop\Entity\Country#__toString()' to get a clue. 

的ActionController(提取):

$forms = $this->getServiceLocator()->get('FormElementManager'); 
$form = $forms->get('Photoshop\Form\CheckoutForm'); 
$customer = new Customer; 
$form->bind($customer); 

$order = new Order; 
$order->setCustomer($customer); 

// Order object is put into a session during checkout process here... 

/** 
* Commit Order to database 
*/ 
$em = $this->getServiceLocator()->get('Doctrine\ORM\EntityManager'); 
$em->persist($sessionCheckout->order); // Fetch the order object from session 
$em->flush(); 

檢驗表

class CheckoutForm extends Form implements ObjectManagerAwareInterface { 

    protected $objectManager; 

    public function __construct() { 
     parent::__construct('checkout'); 

    } 

    public function init() { 

     $this->setAttribute('action', 'checkout'); 
     $this->setAttribute('method', 'post'); 
     $this->setHydrator(new DoctrineHydrator($this->getObjectManager())); 
     $this->setInputFilter(new \Photoshop\Form\CheckoutFilter()); 

     $this->add(array(
      'name' => 'country', 
      'type' => 'DoctrineModule\Form\Element\ObjectSelect', 
      'options' => array(
       'label' => 'Country:', 
       'empty_option' => 'Please choose...', 
       'object_manager' => $this->getObjectManager(), 
       'target_class' => 'Photoshop\Entity\Country', 
       'property' => 'name', 
      ), 
     )); 

     $this->add(array(
      'type' => 'Zend\Form\Element\Select', 
      'name' => 'gender', 
      'options' => array(
       'label' => 'Title*:', 
       'empty_option' => 'Please choose...', 
       'value_options' => array(
        'f' => 'Mrs.', 
        'm' => 'Mr.' 
       ), 
      ) 
     )); 

     $this->add(array(
      'name' => 'firstName', 
      'attributes' => array(
       'type' => 'text', 
       'id' => 'firstName' 
      ), 
      'options' => array(
       'label' => 'First name*:' 
      ), 
     )); 

     $this->add(array(
      'name' => 'lastName', 
      'attributes' => array(
       'type' => 'text', 
       'id' => 'lastName' 
      ), 
      'options' => array(
       'label' => 'Last name*:' 
      ), 
     )); 


     $this->add(array(
      'name' => 'submit', 
      'attributes' => array(
       'type' => 'submit', 
       'value' => 'Pay with PayPal or Credit Card now', 
       'class' => 'btn btn-primary btn-lg btn-block' 
      ) 
     )); 

    } 

    public function setObjectManager(ObjectManager $objectManager) { 
     $this->objectManager = $objectManager; 
    } 

    /** 
    * Get the object manager 
    * 
    * @return ObjectManager 
    */ 
    public function getObjectManager() { 
     return $this->objectManager; 
    } 

} 

I'm相當肯定,這將是簡單的解決。但目前我無法看到解決方案:)

也許有人可以給我一個提示?!?應該理解,...

感謝, 邁克爾

+0

您可以添加創建和存儲客戶的代碼嗎? – jkavalik

+0

當然,我已經添加了控制器(一個提取的版本)和上面的表單類。 – Michael

回答

2

//訂單對象在這裏結帳過程中放入會話... ----這就是重要組成部分

所以,如果我的理解,您可以在一個請求中創建訂單和客戶,然後通過會話將其轉移到其他請求並將其保存在那裏。真正發生的事情是,你有對象圖,像order-> customer-> country,前兩個是新實體,所以序列化反序列化沒有任何問題,但國家是DB中已經存在的管理實體。通過將它序列化到會話中,它從實體管理器中分離出來,並且在反序列化之後,它被呈現給新的實體管理器實例,該實例管理器實例不知道它曾經被管理過,因此決定堅持是新的實體管理器實例。

通常你需要序列化的實體合併到當前實體管理器

$managedOrder = $em->merge($sessionCheckout->order); 

,並與$ managedOrder工作。爲此,您可能需要在Customer :: country和Order :: customer上設置cascade = {「merge」}。

主義有Entities in session有關此主題的文檔頁面。

+0

好吧..聽起來像一個很好的計劃:)我會嘗試,謝謝你的提示 – Michael

+0

太棒了,非常感謝解決方案!我只需另外將級聯更改爲與訂單中n:m關係的訂單項「合併」(未在以上示例中顯示)。 – Michael