2014-01-15 24 views
0

我被卡住了:-)Symfony2單向ManyToMany收集表格

也許我只是在我的研究中有錯誤的關鍵字。但我不明白。所以我希望其中一個人羣能幫助我!

我有一個單向ManyToMany關聯。當我嘗試提交表單(並因此堅持),我得到的錯誤:

A new entity was found through the relationship 'TrainerInnenPool\AppBundle\Entity\Trainer#applicationFields' that was not configured to cascade persist operations for entity: TrainerInnenPool\AppBundle\Entity\[email protected]

當我做「級聯堅持」一個新的實體創建這實際上已經存在。

我有2個實體:

  • 教練
  • ApplicationField

教練員有一個單向多對多聯想到ApplicationField:

class Trainer { 

    public function __construct() 
    { 
     $this->applicationFields = new ArrayCollection(); 
    } 

    [...] 

    /** 
    * @ORM\ManyToMany(targetEntity="ApplicationField") 
    */ 
    protected $applicationFields; 

的ApplicationField具有自引用OneToMany關聯:

class ApplicationField { 

    public function __construct() { 
     $this->children = new ArrayCollection(); 
    } 

    [...] 

    /** 
    * @ORM\OneToMany(targetEntity="ApplicationField", mappedBy="parent") 
    */ 
    private $children; 

    /** 
    * @ORM\ManyToOne(targetEntity="ApplicationField", inversedBy="children") 
    * @ORM\JoinColumn(name="parent_id", referencedColumnName="id") 
    */ 
    private $parent; 

我想創建一個表單,我可以添加一個培訓師 - ApplicationField關聯。

因此我有一個ApplicationFieldCollectionType:

class ApplicationFieldCollectionType extends AbstractType 
{ 
    public function buildForm(FormBuilderInterface $builder, array $options) 
    { 
     $builder 
      ->add('applicationFields', 'collection', array(
       'type'   => new ApplicationFieldType(), 
       'allow_add' => true, 
       'label' => false 
       )) 
     ; 
    } 

    public function setDefaultOptions(OptionsResolverInterface $resolver) 
    { 
     $resolver->setDefaults(array(
      'data_class' => 'TrainerInnenPool\AppBundle\Entity\Trainer', 
     )); 
    } 

的嵌入式類型如下:

class ApplicationFieldType extends AbstractType 
{ 
    public function buildForm(FormBuilderInterface $builder, array $options) 
    { 
     $builder->add('applicationFieldName', 'entity', array(
       'class' => 'TrainerInnenPoolAppBundle:ApplicationField', 
       'label' => false, 
       'mapped' => false, 
       'property' => 'name', 
       'query_builder' => function(EntityRepository $repository) { 
        return $repository->createQueryBuilder('application_field') 
         ->where('application_field.parent is NULL'); 
       } 
     )); 

     $builder->add('name', 'entity', array(
       'class' => 'TrainerInnenPoolAppBundle:ApplicationField', 
       'label' => false, 
       'property' => 'name', 
       'query_builder' => function(EntityRepository $repository) { 
        return $repository->createQueryBuilder('application_field') 
         ->where('application_field.parent = 1'); 
       } 
     )); 
    } 

    public function setDefaultOptions(OptionsResolverInterface $resolver) 
    { 
     $resolver->setDefaults(array(
      'data_class' => 'TrainerInnenPool\AppBundle\Entity\ApplicationField', 
     )); 
    } 

最後遺漏部分:控制器:

public function editApplicationField($id, Request $request) 
    { 
     $entityManager = $this->getDoctrine()->getEntityManager(); 

     $trainer = $entityManager->getRepository('TrainerInnenPoolAppBundle:Trainer')->find($id); 

     $editForm = $this->createForm(new ApplicationFieldCollectionType(), $trainer); 

     if ($request->getMethod() == 'POST') { 

      $editForm->handleRequest($request); 

      $entityManager->flush(); 
     } 

當我取ApplicationField訓練師的實體並試圖堅持那些,

 $editForm->handleRequest($request); 

     $af = $trainer->getApplicationFields(); 

     foreach ($af as $applicationField) { 
      $trainer->addApplicationField($applicationField); 
      $entityManager->persist($applicationField); 
     } 

     $entityManager->flush(); 

我無法這樣做,因爲我得到一個「重複鍵入重複項」 - 例外。

我想我非常想念任何明顯的觀點。如果有人可以幫助我,給我一個提示或剛剛提到用信息更新我的問題,我會非常感激。

親切的問候......

回答

0

那麼你需要級聯=因爲你想與它的關聯ApplicationField堅持整個實體{「堅持」}註解。如果你不使用cascade = {「persist」},你必須手動持久化這些實體。

的實體已經加入到教練,所以如果你想手動堅持實體應刪除線

$trainer->addApplicationField($applicationField); 

,只執行了堅持。

這應該工作。嘗試一下。但是我認爲效果會和使用cascade persist一樣。所以這不是我想的最終解決方案,而是理解問題的第一步,爲什麼手冊堅持以前沒有用。

+0

謝謝,我試過了。的確,這是第一種方法。這種關係持續存在。仍然創建一個新的ApplicationField實體。我認爲這一點在任何我失去參考的地方,儘管在手動持久保存原始ID的情況下ApplicationField實體仍然存在。 – mike

+0

沒錯。已經在想它。我從來沒有使用過單向manytomany,所以這是第一次的經驗。我認爲問題在於,當您向培訓師添加實體時,它無法識別該實體已被管理。嘗試以下操作:循環中的$ entityManager - > getUnitOfWork() - > getEntityState($ applicationField)。檢查實體是否被標記爲託管或新的。如果它們被標記爲新的,問題在於handleRequest方法不能正確處理請求。 – Tobias

+0

確實,狀態是「2」 - > STATE_NEW;所以我想,沒有手動做所有事情都沒有辦法...? – mike

1

你嵌套類型制定者不能說是因爲缺少物業:

->add('applicationFields', 'collection', array(
       'type'   => new ApplicationFieldType(), 
       ... 
       'by_reference' => false 
       ... 

http://symfony.com/doc/current/reference/forms/types/collection.html#by-reference

當您計劃是可添加/刪除的收藏領域(「allow_add」,「allow_delete」) ,您應該始終提供「by_reference」=> false選項,以便直接在相關實體上調用setter,然後構建關聯,而不是從原始實體的鏈式方法。

希望這會有所幫助!