我正在尝试嵌入一系列表单。我有一个任务表单,其中包含一组标记表单:
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());
}
我真的不明白我在这里缺少什么。数据到底在哪里?
答案 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'));
}
}
}
}