Symfony2表单集合自动保留

时间:2014-05-16 05:53:56

标签: symfony doctrine-orm symfony-forms

我正在尝试嵌入一系列表单。我有一个任务表单,其中包含一组标记表单:

public function buildForm(FormBuilderInterface $builder, array $options)
{
    $builder->add('tags', 'collection', array('type' => new TagType()));
}

任务实体包含与标记的一对多关系(没有级联持久化):

/**
 * @ORM\OneToMany(targetEntity="Tag", mappedBy="task", cascade={"remove"})
 */
protected $tags;

标记实体包含与任务的多对一关系:

/**
 * @ORM\ManyToOne(targetEntity="Task", inversedBy="tags")
 * @ORM\JoinColumn(name="task_id", referencedColumnName="id")
 */
protected $task;

我现在有一个Controller,可以编辑其任务的所有标签。如果表单已提交且有效,我想迭代所有标记并决定是否保存标记,但在我的情况下,如果调用$em->flush(),则每个标记都会自动更新和保留,甚至不会在任务或任何标签上调用$em->persist()

public function editTaskAction(Request $request, $id)
{
    $em = $this->getDoctrine()->getManager();
    $task = $em->getRepository('AcmeTaskBundle:Task')->find($id);
    $form = $this->createForm(new TaskType(), $task);
    $form->handleRequest($request);

    if ($form->isValid())
    {
        foreach ($task->getTags() as $tag)
        {
            // TODO decide whether to save the tag or not
        }

        $em->flush();
    }

    return array('form' => $form->createView());
}

我真的不明白我在这里缺少什么。数据到底在哪里?

3 个答案:

答案 0 :(得分:0)

当您使用EntityManager($task)检索$task = $em->getRepository('AcmeTaskBundle:Task')->find($id);时,此实体由EntityManager自动管理,因此$em->persist($task);是隐式的。

例如,createTaskAction()通过创建任务来获取任务的情况并非如此($task = new Task();

在您的情况下,最好的方法是删除foreach ($task->getTags() as $tag)中不需要的标记,对$task->removeTag($tag);执行任何不需要的标记。

答案 1 :(得分:0)

这不是正确的地方。您应该使用prePersist来访问发送给DB的所有数据。在那里您可以决定是否插入新行。 以下是example生命周期的工作原理。

答案 2 :(得分:0)

感谢skowron-line我最终在我的标记实体类中使用了生命周期回调:

use Doctrine\ORM\Event\PreUpdateEventArgs;

/**
 * @ORM\HasLifecycleCallbacks
 */
class Tag
{
    /**
     * @ORM\PreUpdate()
     */
    public function preUpdate(PreUpdateEventArgs $event)
    {
        if ($event->getEntity() instanceof Tag)
        {
            if ($event->hasChangedField('name') && $conditionToAvoidUpdatingEntity)
            {
                $event->setNewValue('name', $event->getOldValue('name'));
            }
        }
    }
}