0

我遇到了一个让我疯狂超过 3 天的问题,但我没有找到任何解决方案。不过,我在 stackoverflow 上发现了一个帖子,这正是我面临的问题。不幸的是,这个人确实设法找到了解决方案,但他或她并没有完全分享。正如他完美解释的那样,只需在下面复制粘贴即可:
顺便说一句,创建该帖子的人似乎只是为这个问题创建了他的帐户,此后再也没有回来处理其他事情。这就是为什么我允许自己再次在这里问...

我有 2 个实体(A 和 B),它们之间存在多对一关系。

我使用 A 实体创建表单,并使用实体字段(下拉列表)来显示 B 实体中的行。我使用查询生成器来过滤它们。如果不更改列表中的值(即使用 ajax),一切正常。

但是,如果我动态更改下拉列表中的值,当我提交表单时,我会收到此错误“此值无效”

这是因为提交的值不包含在查询生成器返回的“数组”中。

似乎这个验证在 symfony 中对于实体字段是自动的(我没有在这个字段上使用任何断言)。我想摆脱这个。但是如何?

看来我需要实现表单事件。不幸的是,我不明白。我阅读了关于该主题的文档非常差,阅读了很多帖子,在互联网上搜索但没有找到任何东西。

下面是我的个人表单类型。我要做的是以下。我创建了第一个实体字段类型,并将映射属性设置为 false 并过滤实体以获取部门。然后我创建另一个实体类型,称为本地化。默认情况下,我过滤实体以获取任何内容('')。然后我要做的是使用 Jquery 来填充它。但不幸的是,我遇到了与其他伙伴相同的问题(见上文)。

use Symfony\Component\Form\FormBuilderInterface;
use FOS\UserBundle\Form\Type\RegistrationFormType as BaseType;
use Doctrine\ORM\EntityRepository;
use Auth\GeoBundle\Form\LocalisationType;


class RegistrationFormType extends BaseType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        parent::buildForm($builder, $options);

        $builder->add('departement', 'entity', array(
            'mapped' => false,
            'empty_value' => '',
            'class' => 'AuthGeoBundle:Localisation',
            'property' => 'departement',
            'query_builder' => function ($repository) {
                return $repository
                    ->createQueryBuilder('e')
                    ->add('groupBy', 'e.departement')
                ;
            },
        ));


        $builder->add('localisation', 'entity', array(
            'empty_value' => '',
            'class' => 'AuthGeoBundle:Localisation',
            'property' => 'formLabel',
            'query_builder' => function ($repository) use ($dpt) {
                return $repository
                    ->createQueryBuilder('e')
                    ->where('e.departement = :dpt')
                    ->setParameter('dpt', '')
                    ->add('orderBy', 'e.ville ASC')
                ;
            },
        ));

        //some other fields here...
    }

    public function getName()
    {
        return 'auth_user_registration';
    }
}
4

2 回答 2

2

我终于设法使用表单事件找到解决方案。我在http://symfony.com/doc/current/cookbook/form/dynamic_form_generation.html上玩过“教程”并让它工作:) 下面是我使用的代码,以防有人感兴趣。

我的表单类型:

<?php
//src/Auth/UserBundle/Form/Type/RegistrationFormType.php
namespace Auth\UserBundle\Form\Type;

use Symfony\Component\Form\FormBuilderInterface;
use FOS\UserBundle\Form\Type\RegistrationFormType as BaseType;
use Doctrine\ORM\EntityRepository;
use Auth\GeoBundle\Form\LocalisationType;

use Auth\UserBundle\Form\EventListener\IsAdminFieldSubscriber;

class RegistrationFormType extends BaseType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        parent::buildForm($builder, $options);

        //NE PAS EFFACER -> exempled e comment ajouter un champ qui n'a rien à voir avec nos entitys
        //$builder->add("firstName", "text", array("mapped" => false));

        $builder->add('departement', 'genemu_jqueryselect2_entity', array(
            'mapped' => false,
            'empty_value' => '',
            'class' => 'AuthGeoBundle:Localisation',
            'property' => 'departement',
            'query_builder' => function ($repository) {
                return $repository
                    ->createQueryBuilder('e')
                    ->add('groupBy', 'e.departement')
                ;
            },
        ));


        $dpt = "";
        $builder->add('localisation', 'genemu_jqueryselect2_entity', array(
            'empty_value' => '',
            'class' => 'AuthGeoBundle:Localisation',
            'property' => 'formLabel',
            'query_builder' => function ($repository) use ($dpt) {
                return $repository
                    ->createQueryBuilder('e')
                    ->where('e.departement = :dpt')
                    ->setParameter('dpt', $dpt)
                    ->add('orderBy', 'e.ville ASC')
                ;
            },
        ));

        $builder->add('sexe', 'genemu_jqueryselect2_choice', array(
            'empty_value' => '',
            'choices'   => array(
                'homme'   => 'Homme',
                'femme' => 'Femme',
            ),
            'configs' => array(
                'minimumResultsForSearch' => 5,
            )
        ));

        $builder->add('date_naissance', 'date', array(
            'empty_value' => '',
            'widget' => 'choice',
            'attr' => array('class' => 'input-small'),
            'years' => range(1900,2100),
            'months' => range(1,12),
            'days' => range(1,31),
        ));

        $builder->add('petit_mot');

        $subscriber = new IsAdminFieldSubscriber($builder->getFormFactory());
        $builder->addEventSubscriber($subscriber);
    }


    public function getName()
    {
        return 'auth_user_registration';
    }
}

我的事件监听器:

<?php
//src/Auth/UserBundle/Form/EventListener/isAdminFieldSubscriber.php
namespace Auth\UserBundle\Form\EventListener;

use Symfony\Component\Form\Event\DataEvent;
use Symfony\Component\Form\FormFactoryInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\Form\FormEvents;

class IsAdminFieldSubscriber implements EventSubscriberInterface
{
    /**
     * @var FormFactoryInterface 
     */
    private $factory;

    /**
     * @param FormFactoryInterface $factory 
     */
    public function __construct(FormFactoryInterface $factory)
    {
        $this->factory = $factory;
    }

    /**
     * @return array
     */
    public static function getSubscribedEvents()
    {
        return array(
            FormEvents::PRE_BIND => 'preBind',
        );
    }

    /**
     * Called before form data is set
     *
     * @param DataEvent $event
     */
    public function preBind(DataEvent $event)
    {
        $data = $event->getData();
        $form = $event->getForm();

        if (null === $data) {
            return;
        }

        $dpt = $data['localisation'];

        $form->add($this->factory->createNamed('localisation', 'entity', null, array(
            'empty_value' => '',
            'class' => 'AuthGeoBundle:Localisation',
            'property' => 'formLabel',
            'query_builder' => function ($repository) use ($dpt)  {
                return $repository
                    ->createQueryBuilder('e')
                    ->where('e.id = :dpt_id')
                    ->setParameter('dpt_id', $dpt)
                    ->add('orderBy', 'e.ville ASC')
                ;
            },
        )));
    }

}
于 2013-01-22T22:39:32.737 回答
0

You explain the problem yourself:

"It's because the submitted value isn't included in the "array" returned by the query builder."

You can use data transformers to solve this issue.

于 2013-01-22T14:58:55.160 回答