Динамическая форма Symfony (POST_SUBMIT), значение NULL в атрибутах вложенных объектов - PullRequest
0 голосов
/ 15 января 2019

У меня есть вопрос о событиях формы Symfony, у меня есть 2 объекта: Пользователь и Адрес, Пользователь может иметь mainAddress и subAddress, он также может использовать один и тот же адрес (mainAddress) для обоих.

Но когда я редактирую пользователя, у которого ранее был подадрес, потому что мы отправляем форму без данных о подадресе, в POST_SUBMIT она устанавливает нулевое значение в полях. В моем случае я хочу заполнить его предыдущим объектом.

У меня есть пользовательский объект:

class User
{

    ...

    /**
     * @ORM\ManyToOne(targetEntity="App\Entity\Address", cascade={"persist", "remove"})
     * @ORM\JoinColumn(nullable=true)
     * @Assert\Valid()
     */
    private $mainAddress;

    /**
     * @ORM\ManyToOne(targetEntity="App\Entity\Address", cascade={"persist", "remove"})
     * @ORM\JoinColumn(nullable=true)
     * @Assert\Valid()
     */
    private $subAddress;
}

И адрес объекта:

class Address
{
    /**
     * @ORM\Column(type="string", length=255)
     * @Assert\NotBlank()
     */
    private $country;

    /**
     * @ORM\Column(type="string", length=255)
     * @Assert\NotBlank()
     */
    private $fullName;

    ...
}

Тип формы адреса:

class AddressType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('country', CountryType::class, [
                'label' => 'label.country',
                'preferred_choices' => ['FR'],
            ])
            ->add('fullName', TextType::class, [
                'label' => 'label.full_name',
            ])

            ...

        ;
    }

    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults([
            'data_class' => Address::class,
        ]);
    }
}

И, наконец, мой UserType, использующий EventListeners:

class UserType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options): void
    {
        $builder
            ->add('email', EmailType::class, [
                'label' => 'label.email',
            ])
            ->add('mainAddress', AddressType::class)
            ->add('singleAddress', CheckboxType::class, [
                'required' => false,
            ])
        ;

        $formSubAddressModifier = function (FormInterface $form, bool $singleAddress) {
            if (false === $singleAddress && false === $form->has('subAddress')) {
                $form->add('subAddress', AddressType::class);
            } elseif (true === $singleAddress && true === $form->has('subAddress')) {
                $form->remove('subAddress');
            }
        };

        $builder->addEventListener(FormEvents::PRE_SET_DATA, function (FormEvent $event) use ($formSubAddressModifier) {
            $formSubAddressModifier($event->getForm(), $event->getData()->getSingleAddress());
        });

        $builder->get('singleAddress')->addEventListener(FormEvents::POST_SUBMIT, function(FormEvent $event) use ($formSubAddressModifier) {
            $singleAddress = $event->getForm()->getData();

            $formSubAddressModifier($event->getForm()->getParent(), $singleAddress);
        });
    }

    public function configureOptions(OptionsResolver $resolver): void
    {
        $resolver->setDefaults([
            'data_class' => User::class,
        ]);
    }
}

...