dse323222 2018-12-03 15:50
浏览 37

Symfony:动态更改表单字段会抛出现有实体的异常

I'm trying to do a Form that creates a new Notificacion that can be related to:

  • An existing Vecino
  • A new Vecino
  • None of the above

And Vecino is related to a Domicilio

Also I have a ModeloImpresion that depends on an Area field (both from Notificacion)

What I want to do is a form where I create the Notificacion with a field Area that changes the ModeloImpresion field. So i followed the steps on https://symfony.com/doc/3.4/form/dynamic_form_modification.html#form-events-submitted-data

If I make one without Vecino it works, if i create a new Vecino it works but when I have to create one with an existing Vecino the AJAX fails with the following Exception when handling the Request (the Entities have other fields not related to the error so I didn't copy them):

Type error: Argument 1 passed to Proxies\__CG__\Brown\TurnoBundle\Entity\Vecino\Domicilio::setCalle() must be of the type string, null given, called in /home/gonchi/web/vendor/symfony/symfony/src/Symfony/Component/PropertyAccess/PropertyAccessor.php on line 623

I checked and if I dump the Notificacion it has the correct Vecino with the correct Domicilio that has a calle defined.

I don't know where it goes wrong

The schema of relations is:

class Notificacion
{
    /**
     * @var null|Vecino
     *
     * @ORM\ManyToOne(targetEntity="Brown\TurnoBundle\Entity\Vecino")
     */
    private $vecino;

    /**
     * @var Area|null
     *
     * @ORM\ManyToOne(targetEntity="Brown\BrownBundle\Entity\Area")
     */
    private $area;

    /**
     * @var DatosFijos\ModeloImpresion|null
     *
     * @ORM\ManyToOne(targetEntity="Brown\BrownBundle\Entity\DatosFijos\ModeloImpresion")
     */
    private $modeloImpresion;
}

class Vecino
{
    /**
     * @var null|Domicilio
     *
     * @ORM\ManyToOne(targetEntity="Brown\TurnoBundle\Entity\Vecino\Domicilio", cascade={"persist", "remove"})
     */
    private $domicilio;
}

Here's my controller:

/**
 * @param Request $request
 *
 * @return Response|\Symfony\Component\HttpFoundation\RedirectResponse
 */
public function nuevoAction(Request $request)
{
    // This comes from a search on the repository. 
    // If it finds a Vecino it returns the object.
    // If it didn't find one it returns null.
    // If this Notificacion shouldn't have a Vecino it returns false
    $vecino = $this->getSessionVariable(Constants::SESSION_VECINO);

    $notificacion = new Notificacion();

    // If there should be a Vecino but didn't find one it creates one
    if ($vecino === null) {
        $vecino = new Vecino();
        $vecino->setDni($this->getSessionVariable(Constants::SESSION_DNI_CUIL));
    }

    // If there's a Vecino (existing or new) it sets it to the Notificacion
    if ($vecino) {
        $notificacion->setVecino($vecino);
    }

    $form = $this->createForm(NuevoType::class, $notificacion);

    $form->handleRequest($request);

    if ($form->isSubmitted() && $form->isValid()) {

        // A shortcut to $this->getEm()->persist()
        $this->saveToDatabase($notificacion);

        return $this->redirectToRoute('admin_notificacion_listado');
    }

    return $this->render('@Admin/Notificacion/nuevo.html.twig', [
        'form' => $form->createView(),
    ]);
}

And my Form:

class NuevoType extends AbstractType
{
    /**
     * @var AreaRepository|\Doctrine\ORM\EntityRepository
     */
    private $areaRepository;

    /**
     * @var \Brown\BrownBundle\Repository\DatosFijos\ModeloImpresionRepository | \Doctrine\ORM\EntityRepository
     */
    private $modeloImpresionRepository;

    public function __construct(EntityManager $entityManager)
    {
        $this->areaRepository            = $entityManager->getRepository(Area::class);
        $this->modeloImpresionRepository = $entityManager->getRepository(ModeloImpresion::class);
    }

    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        // Check so it only add it if there should be one
        if ($builder->getData()->getVecino()) {
            $builder->add('vecino', VecinoMinimoType::class, [
                'label' => false,
            ]);
        }


        $builder
            ->add('area', EntityType::class, [
                'class'        => Area::class,
                'choice_label' => 'nombre',
                'query_builder' => function (AreaRepository $er) {
                    return $er->createQueryBuilder('a')
                        ->orderBy('a.nombre', 'ASC');
                },
                'placeholder' => 'Seleccione el área',
                'attr' => ['class' => 'area-entity']
            ])
            ->add('submit', SubmitType::class, [
                'label' => 'Guardar',
                'attr'  => ['class' => 'btn btn-primary'],
            ])
        ;

        $formModifier = function (FormInterface $form, Area $area = null) {
            $modelosImpresion = null === $area ? [] : $this->modeloImpresionRepository->findByAreas([$area]);

            $form->add('modeloImpresion', EntityType::class, [
                    'label'   => 'Tipo de Notificación',
                    'class'   => ModeloImpresion::class,
                    'choices' => $modelosImpresion,
                    'attr' => ['class' => 'modeloImpresion-entity'],
            ]);
        };


        $builder->addEventListener(FormEvents::PRE_SET_DATA, function (FormEvent $event) use ($formModifier) {
            /** @var Notificacion $notificacion */
            $notificacion = $event->getData();
            $form = $event->getForm();

            $formModifier($event->getForm(), $notificacion->getArea());
        });



        $builder->get('area')->addEventListener(
            FormEvents::POST_SUBMIT,
            function (FormEvent $event) use ($formModifier) {
                $area = $event->getForm()->getData();
                $formModifier($event->getForm()->getParent(), $area);
            }
        );

    }

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

And finally the Javascript on my view:

<script>
    var area = $('.area-entity');

    area.change(function() {
        var form = $(this).closest('form');
        var data = {};
        data[area.attr('name')] = area.val();
        $.ajax({
            url : form.attr('action'),
            type: form.attr('method'),
            data : data,
            success: function(html) {
                var modeloImpresion = $('.modeloImpresion-entity');
                modeloImpresion.replaceWith(
                    $(html).find('.modeloImpresion-entity')
                );
            },
        });
    });
</script>
  • 写回答

0条回答 默认 最新

    报告相同问题?

    悬赏问题

    • ¥15 我的数据无法存进链表里
    • ¥15 神经网络预测均方误差很小 但是图像上看着差别太大
    • ¥15 Oracle中如何从clob类型截取特定字符串后面的字符
    • ¥15 想通过pywinauto自动电机应用程序按钮,但是找不到应用程序按钮信息
    • ¥15 如何在炒股软件中,爬到我想看的日k线
    • ¥15 seatunnel 怎么配置Elasticsearch
    • ¥15 PSCAD安装问题 ERROR: Visual Studio 2013, 2015, 2017 or 2019 is not found in the system.
    • ¥15 (标签-MATLAB|关键词-多址)
    • ¥15 关于#MATLAB#的问题,如何解决?(相关搜索:信噪比,系统容量)
    • ¥500 52810做蓝牙接受端