2014-12-01 51 views
5

的形式由哪幾種答案,這樣的答案可以爲每個問題被動態地創建一個問題。這東西一切工作正常:Symfony2的形式,對象的集合,發行更新現有對象屬性

public function buildForm(FormBuilderInterface $builder, array $options) 
{ 
    $builder 
     ->add('question','textarea') 
     ->add('answers', 'collection', array(
      'type'=>new AnswerType(), 
      'allow_add'=>true, 
      'allow_delete'=>true, 
      'label' => false 
     )) 
    ; 
} 

這裏是AnswerType表單代碼:

$builder 
     ->add('answer','text', array(
      'attr'=>array(
       'class'=>'form-control' 
      ), 
      'label'=>false 
     )) 
     ->add('isGoodAnswer', 'checkbox', array(
      'label'=>'Good?', 
      'required'=>false 
     )) 
    ; 

我使用的原型模板通過jQuery來填充容器。

添加新的答案對象的問題對象工作正常。刪除答案也不是問題。

但是,如果我去上收集表單輸入時不更新現有的對象一個更新現有的財產。它堅持問題對象,因爲它會更新問題本身的文本。我只能刪除並創建新的目前替換的東西,我很難找出原因。

下面是從模板形式的代碼片段提交:

<ul id="answer-fields-list" data-prototype="{{ form_widget(form.answers.vars.prototype)|e }}"> 
    {% for answer in form.answers %} 
     <li> 
      <div class='col-md-12'>     
       {{ form_widget(answer) }}     
       <div> 
        <a href='#' class='btn btn-sm btn-danger delete-this'><span class='glyphicon glyphicon-trash'></span></a> 
       </div> 
      </div>     
     </li> 
    {% endfor %} 
    </ul>   
    <a href="#" id="add-answer" class='btn btn-sm btn-success'><span class='glyphicon glyphicon-plus-sign'></span> Add Answer</a>   

編輯,這裏是本次更新的方法全控制器代碼:

$question = $em->getRepository('ChecklistMainBundle:ChecklistQuestion')->findOneById($questionId); 
    if(!$question) throw new NotFoundHttpException('Question not found'); 

    $form = $this->createForm(new QuestionAnswerType(), $question); 

    $form->handleRequest($request); 

    if($request->getMethod()=='POST' && $form->isValid()) 
    { 
     if($form->get('attachment')->getData() != null) { 
      $question->uploadAttachment(); 
     } 
     $em->persist($question); 
     $em->flush(); 

     $this->get('session')->getFlashBag()->add('success', 'Question was modified successfully!'); 

     return $this->redirect($this->generateUrl('admin_checklists_view', array('id'=>$id))); 
    } 
+0

你應該共享的代碼,其中代碼段你處理輸入 – 2014-12-01 23:27:58

+0

嘿米迦勒,我只是做'$ form-> handleRequest($ request);'然後堅持$問題對象。這個表單是通過symfony2表單生成器'$ form = $ this-> createForm(new QuestionAnswerType(),$ question);' – skrilled 2014-12-02 20:36:14

+1

創建的,只是爲了闡明我的理解是正確的:你的更改持久存在於數據庫中,但是對象不是在PHP代碼中進行了修改,表單用老東西渲染,對吧?你的方法看起來很好(通過本書)。我要求輸入代碼片段,因爲可能存在重新創建對象,再次呈現它,從數據庫而不是表單等讀取它的一些小錯誤。 – 2014-12-03 08:11:55

回答

3

通過Google搜索幾個小時後,我遇到了類似於我的重複問題。

How to force Doctrine to update array type fields?

我通過setAnswers方法如下調整,以反映這樣的回答:

public function setAnswers($answers) 
    { 
     if(!empty($answers) && $answers === $this->answers) { 
      reset($answers); 
      $answers[key($answers)] = clone current($answers); 
     } 
     $this->answers = $answers; 
     return $this; 
    } 

現在節省現有的回答很好,沒有更多的問題:)

+0

你沒有指定關聯和所有關於'OneToMany'關係的想法。更優雅的方式是調用'$ uow-> propertyChanged($ entity,$ propertyName,$ oldValue,$ newValue)'(例如,在偵聽器中)。 – origaminal 2014-12-09 04:09:22

+0

即使你更喜歡克隆,也可以通過'by_reference => false'來完成'AnswerType'選項。 – origaminal 2014-12-09 15:48:18

+0

情況並非如此。我試過這些,它對我沒有任何幫助,如果我正在使用託管實體而不是簡單的php對象,那將會起作用。由於我使用的是對象集合而不是實體集合,因此實體管理器只會識別集合發生了更改,而不會更改集合中對象的屬性。 – skrilled 2014-12-12 22:31:08

1

,我認爲你應該使用合併以更新對象:

$em->merge($question) 
$em->flush(); 
+3

Question實體被EntityManager找到,因此已經被管理。閱讀[文檔](http://doctrine-orm.readthedocs.org/en/latest/reference/working-with-objects.html#merging-entities)瞭解merge()實際上做了什麼。此外,問題仍然存在,這是一個答案(在特定的使用情況下)不是。 – 2014-12-05 16:13:41

1

An瑞士人不會堅持自己。

或者:

foreach ($question->getAnswers() as $answer) { 

    $em->persist($answer); 
} 

$em->persist($question); 
$em->flush(); 

或(在你的問題的實體):

/** 
* @ORM\OneToMany(targetEntity="YourBundle\Etc\Entity\Answer",mappedBy="question",cascade={"persist"}) 
*/ 

More info.

+2

實際上,如果您尚未更改默認的更改跟蹤策略,則管理實體_will_自身更新(或者更確切地說,工作單元將會持續更改,這些更改會使用默認更改跟蹤策略自動檢測到)。 – 2014-12-05 16:15:35

+0

在我引用的鏈接中說:「默認情況下,沒有操作級聯」。除非我錯過了一些東西,否則這些東西看起來非常乾淨。問題是爲什麼不改變答案實體並且我的答案似乎由文檔支持。 – Richard 2014-12-08 00:54:17

+1

'cascade = persist'將確保添加到集合/關聯的_new_實體被保留,這實際上不會默認完成。但我們正在討論在這裏更新現有實體:) – 2014-12-08 10:17:39

1

添加兩個addAnswer()removeanswer()你的問題的實體/模型。

集收集的by_reference選項false

$builder 
     ->add('question','textarea') 
     ->add('answers', 'collection', array(
      'type'=>new AnswerType(), 
      'allow_add'=>true, 
      'allow_delete'=>true, 
      'label' => false, 
      'by_reference' = > false 
     )) 
    ; 
+0

嘗試了這一點,但仍然只能讓我添加和刪除,而不是更新現有對象 – skrilled 2014-12-08 19:21:41

1

您可能要的handleRequest調用後對象圖前比較。

我建議你使用\Doctrine\Common\Util\Debug::dump();,就會使輸出更短。

另一件事是檢查原始請求數據本身,看是否提交的數據本身是正確的:只要使用表格網頁調試工具條選項卡(或請求,根據)。

現在爲什麼它的行爲一樣,很難回答。 集合類型行爲會非常不同給你by_reference或對其進行配置:

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

,如果你使用的是集合形式鍵入您底層集合數據對象(像學說的ArrayCollection中) ,那麼如果你需要setter(例如setAuthors())被調用,則必須將by_reference設置爲false。

https://github.com/symfony/symfony/blob/master/src/Symfony/Component/Form/Extension/Core/EventListener/ResizeFormListener.php在這裏起到了很大的作用。正如你所看到的,排序很重要。

驗證提交的數據是否處於預期的順序。

末(或者檢查這第一:)),大部分時間collection只是工作:) 確認兩次,你的getter和setter方法不包含一個棘手的拼寫錯誤,而攪亂whiole件事:

通過模仿表單組件可以做什麼來手動嘗試。

希望它有幫助!

+0

嘗試了所有這些,在弄亂周圍的過程中發現我*可以*編輯現有對象if並且只有在我同時添加或刪除另一個對象時也是如此。即如果我編輯答案的文本,但同時也添加一個新的答案 - 它的工作原理。儘管如此,仍然試圖找出一種方法來做到這一點,但沒有這些漏洞。 – skrilled 2014-12-08 19:38:38