簡體   English   中英

symfony2表單,對象集合,問題更新現有對象屬性

[英]symfony2 form, collection of objects, issue updating existing object property

表單由一個問題組成,該問題有幾個答案,因此可以為每個問題動態創建答案。 這些東西一切正常:

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

在谷歌搜索了幾個小時后,我遇到了一個類似於我的重復問題。

如何強制Doctrine更新數組類型字段?

我通過setAnswers方法調整如下以反映這個答案:

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

它現在保存現有的答案很好,沒有更多的問題:)

addAnswer()removeanswer()到Question實體/模型中。

將集合的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
        ))
    ;

我認為你應該使用merge來更新對象:

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

答案不會持續存在。

或者:

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

    $em->persist($answer);
}

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

或者(在您的問題實體中):

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

更多信息。

您可能希望比較handleRequest調用之前之后的對象圖。

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

要檢查的另一件事是原始請求數據本身,以查看提交的數據本身是否正確:只需使用表格web調試工具欄選項卡(或請求,取決於)。

現在為什么它的行為很難回答。 如果使用by_reference配置它, by_reference集合類型的行為會有很大不同:

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

如果您正在使用集合表單類型,其中您的基礎集合數據是一個對象(如與Doctrine的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的事情:

如果需要,可以手動嘗試,模仿表單組件。

希望能幫助到你!

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM