Symfony2表单集合自动持久化

Symfony2表单集合自动持久化,symfony,doctrine-orm,symfony-forms,Symfony,Doctrine Orm,Symfony Forms,我正在尝试嵌入一个表单集合。我有一个任务表单,其中包含一组标记表单: public function buildForm(FormBuilderInterface $builder, array $options) { $builder->add('tags', 'collection', array('type' => new TagType())); } 任务实体包含与标记的一对多关系(无级联持久): 标记实体包含与任务的多对一关系: /** * @ORM\ManyT

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

public function buildForm(FormBuilderInterface $builder, array $options)
{
    $builder->add('tags', 'collection', array('type' => new TagType()));
}
任务实体包含与标记的一对多关系(无级联持久):

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

/**
 * @ORM\ManyToOne(targetEntity="Task", inversedBy="tags")
 * @ORM\JoinColumn(name="task_id", referencedColumnName="id")
 */
protected $task;
我现在有一个控制器,它可以编辑其任务的所有标记。如果表单已提交且有效,我希望遍历所有标记并决定是否保存标记,但在我的情况下,如果调用了
$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());
}

我真的不明白我错过了什么。数据具体保存在哪里?

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

例如,在您的
createTaskAction()
中,您不是通过创建任务来获得任务的(
$Task=newtask();


在您的情况下,最好是通过执行类似于
$task->removeTag($tag)的操作来删除
foreach($task->getTags()as$tag)
中不需要的标记用于任何不需要的标记。

这不是执行此操作的正确位置。您应该使用
prePersist
,在其中您可以访问发送到数据库的所有数据。在这里,您可以决定是否插入新行。 以下是生命周期的工作原理。

多亏了我在标记实体类中使用了生命周期回调:

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