【问题标题】:Symfony CollectionType: Merge new entriesSymfony CollectionType:合并新条目
【发布时间】:2018-05-29 11:43:05
【问题描述】:

我的 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();
    }

【问题讨论】:

  • 你试过ArrayCollection的添加方式吗?比如:$this->attachments->add($attachment);
  • 你是在构造函数中将 $attachments 实例化为一个新的 ArrayCollection() 吗?
  • 'by_reference' => false 不会导致 Symfony 调用 $this->attachments->add($attachmetn)?是的,我在构造函数中将 $attachments 实例化为新的 ArrayCollection。抱歉,我错过了上面的内容
  • 你有 '$this->attachments[] = $attachment;'尝试使用 ArrayCollection 方法 '$this->attachments->add($attachment);'我不认为它是自动调用的,不。

标签: forms symfony doctrine-orm symfony-forms symfony-3.2


【解决方案1】:

有几种方法可以做你想做的事。最简单的方法是为您的表单字段提供空数据或新附件实体:

$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'

并创建 addAppendAttachmentremoveAppendAttachment

public function addAppendAttachment(Attachment $attachment) {
    $attachment->setMail($this);
    $this->attachments[] = $attachment;
    return $this;
}

public function removeAppendAttachment(Attachment $attachment) {
    return $this;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-01
    • 1970-01-01
    • 2017-01-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多