符号形式 - 允许删除嵌套形式相关的实体



我有一个/checkout JSON API端点,该端点允许可选的billingAddress参数与其他参数,例如电子邮件和deliveryAddress

这些地址存储在与Order实体有关的Address实体中。

如果用户输入其BillingAddress,一切都很好,但是如果用户删除先前提交的帐单地址,我找不到删除billingAddress Entity的方法。理想情况下,要删除我使用以下JSON帖子请求的计费地址。

{
    "email": "nick@example.com",
    "deliveryAddress": {
        "line1": "1 Box Lane"
    },
    "billingAddress": null
}

这根本有可能使用Symfony表格?

有关当前设置的简化说明,请参见下文。

实体

/**
 * @ORMEntity
 */
class Order
{
    // ...
    /**
     * @var Address
     *
     * @ORMOneToOne(targetEntity = "Address", cascade = {"persist", "remove"})
     * @ORMJoinColumn(name = "deliveryAddressId", referencedColumnName = "addressId")
     */
    private $deliveryAddress;
    /**
     * @var Address
     *
     * @ORMOneToOne(targetEntity = "Address", cascade = {"persist", "remove"}, orphanRemoval = true)
     * @ORMJoinColumn(name = "billingAddressId", referencedColumnName = "addressId", nullable = true)
     */
    private $billingAddress;
    public function setDeliveryAddress(Address $deliveryAddress = null)
    {
        $this->deliveryAddress = $deliveryAddress;
        return $this;
    }
    public function getDeliveryAddress()
    {
        return $this->deliveryAddress;
    }
    public function setBillingAddress(Address $billingAddress = null)
    {
        $this->billingAddress = $billingAddress;
        return $this;
    }
    public function getBillingAddress()
    {
        return $this->billingAddress;
    }
    // ...
}

/**
 * @ORMEntity
 */
class Address
{
    // ...
    /**
     * @var string
     *
     * @ORMColumn(type = "string", length = 45, nullable = true)
     */
    private $line1;
    // ...
}

表格

class CheckoutType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('email', EmailType::class)
            ->add('deliveryAddress', AddressType::class, [
                'required' => true
            ])
            ->add('billingAddress', AddressType::class, [
                'required' => false
            ]);
    }
    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults([
            'data_class' => Order::class,
            'csrf_protection' => false,
            'allow_extra_fields' => true,
            'cascade_validation' => true
        ]);
    }
    public function getBlockPrefix()
    {
        return '';
    }
}

class AddressType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            // ...
            ->add('line1', TextType::class);
            // ...
    }
    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults([
            'data_class' => Address::class,
            'allow_extra_fields' => true
        ]);
    }
    public function getBlockPrefix()
    {
        return '';
    }
}

表单事件是您需要的:https://symfony.com/doc/current/form/form/events.html

例如,如果要在表单提交后删除billingAddress字段,则可以这样做:

public function buildForm(FormBuilderInterface $builder, array $options)
{
    $builder
        ->add('email', EmailType::class)
        ->add('deliveryAddress', AddressType::class, [
            'required' => true
        ])
        ->add('billingAddress', AddressType::class, [
            'required' => false
        ]);
    $builder->addEventListener(FormEvents::PRE_SUBMIT, function(FormEvent $event) {
        $form = $event->getForm();
        $data = $event->getData();
        if (empty($data['billingAddress'])) {
            $form->remove('billingAddress');
        }
    });
}

仔细阅读文档以了解哪个事件将是您的场景。

尝试将" billingaddress"字段的" by_reference"选项设置为false,以确保称为设置器。

http://symfony.com/doc/current/referent/forms/types/form.html#by-reference

非常感谢雷南(Renan)和拉斐尔(Raphael)的答案,因为我发现了下面的解决方案,该解决方案既适用于部分补丁和完整的帖子请求。

class CheckoutType extends AbstractType
{
    /** @var bool */
    private $removeBilling = false;
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('email', EmailType::class)
            ->add('deliveryAddress', AddressType::class, [
                'constraints' => [new Valid]
            ])
            ->add('billingAddress', AddressType::class, [
                'required' => false,
                'constraints' => [new Valid]
            ])
            ->addEventListener(FormEvents::PRE_SUBMIT, [$this, 'onPreSubmit'])
            ->addEventListener(FormEvents::POST_SUBMIT, [$this, 'onPostSubmit']);
    }
    public function onPreSubmit(FormEvent $event)
    {
        $data = $event->getData();
        $this->removeBilling = array_key_exists('billingAddress', $data) && is_null($data['billingAddress']);
    }
    public function onPostSubmit(FormEvent $event)
    {
        if ($this->removeBilling) {
            $event->getData()->setBillingAddress(null);
        }
    }
}

相关内容

  • 没有找到相关文章

最新更新