symfony2表单,对象集合,问题更新现有对象属性

时间:2014-12-01 22:41:30

标签: php symfony doctrine-orm

表单由一个问题组成,该问题有几个答案,因此可以为每个问题动态创建答案。这些东西都很好用:

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

5 个答案:

答案 0 :(得分:4)

在谷歌搜索了几个小时后,我遇到了一个类似于我的重复问题。

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

它现在可以很好地保存现有答案,而不是更多问题:)

答案 1 :(得分:2)

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

答案 2 :(得分:1)

我认为你应该使用merge来更新对象:

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

答案 3 :(得分:1)

答案不会自行存在。

或者:

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.

答案 4 :(得分:1)

您可能希望比较<{strong>之前之前的和<{strong>之后之后的对象图。

我建议你使用handleRequest,它会缩短输出。

要检查的另一件事是原始请求数据本身,以查看提交的数据本身是否正确:只需使用表单web调试工具栏选项卡(或请求,取决于)。

现在为什么它的行为很难回答。 如果您使用\Doctrine\Common\Util\Debug::dump();配置它,则集合类型的行为会有很大不同:

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在这里肯定发挥了重要作用。 如您所见,订购很重要。

验证提交的数据是否符合预期的顺序。

最后(或者可能首先检查:)),大部分时间by_reference只是工作:) 验证你的吸气剂和制定者不会包含一些混乱的拼写错误,这些错误会让人不知所措:

如果需要,请手动尝试,模仿表单组件的内容。

希望它有所帮助!