我的symfony表单代表一个实体Mail
,它与另一个名为Attachment
的实体有一对多关系。因此,MailType
表单包含CollectionType
字段,用于嵌入其AttachmentType
表单:
$builder
->add('attachments', CollectionType::class, [
'entry_type' => AttachmentType::class,
'allow_add' => true,
'allow_delete' => false,
'by_reference' => false,
]);
我的视图只会向Symfony后端发送新附件。因此,在将表单数据存储到数据库中时,我只想添加邮件的新附件,而不要触及任何现有附件。
不幸的是,Symfony / Doctrine的行为有所不同:如果表单数据中包含n
附件,那么n
首先存在的附件会被这些新附件覆盖:
existing attachments (in DB): [old1, old2, old3]
new attachments (contained by HTTP request): [new1, new2]
desired result in DB: [old1, old2, old3, new1, new2]
actual result in DB: [new1, new2, old3]
我怎样才能做到这一点?我认为by_reference => false
会导致addAttachment
方法被调用,所以我也希望这可以开箱即用。
我的Mail
实体代码:
class Mail {
/**
* @ORM\OneToMany(targetEntity="AppBundle\Entity\Attachment", mappedBy="mail", cascade={"persist", "remove"})
*/
protected $attachments;
...
public function addAttachment(\AppBundle\Entity\ttachment $attachment) {
$attachment->setMail($this);
$this->attachments[] = $attachment;
return $this;
}
}
我的控制器代码处理表单:
// $mail = find mail in database
$form = $this->createForm(MailType::class, $mail);
$form->handleRequest($request);
if ($form->isValid()) {
$mail = $form->getData();
$em = $this->getDoctrine()->getManager();
$em->persist($mail);
$em->flush();
}
答案 0 :(得分:0)
有几种方法可以做你想要的。最简单的方法是在表单字段中提供空数据或新附件实体:
$builder
->add('attachments', CollectionType::class, [
'entry_type' => AttachmentType::class,
'allow_add' => true,
'allow_delete' => true,
'by_reference' => false,
'data' => [new Attachment()] // or add more or []
]);
然后在你的邮件实体中:
public function addAttachment(Attachment $attachment) {
$attachment->setMail($this);
$this->attachments[] = $attachment;
return $this;
}
public function removeAttachment(Attachment $attachment) {
return $this;
}
如果您使用 removeAttachment 来执行某些其他功能,并且您实际上已删除了附件,则可以利用表单字段的 property_path 设置:
'property_path' => 'appendAttachments'
并创建 addAppendAttachment 和 removeAppendAttachment :
public function addAppendAttachment(Attachment $attachment) {
$attachment->setMail($this);
$this->attachments[] = $attachment;
return $this;
}
public function removeAppendAttachment(Attachment $attachment) {
return $this;
}