【问题标题】:Symfony 2 - How to validate Entity Field Type when it is populated using Ajax?Symfony 2 - 如何在使用 Ajax 填充时验证实体字段类型?
【发布时间】:2013-01-22 14:11:36
【问题描述】:

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

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

我使用 A 实体创建表单并使用实体字段(下拉 list) 以显示 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';
    }
}

【问题讨论】:

    标签: forms symfony doctrine-orm validation


    【解决方案1】:

    我终于设法使用表单事件找到了解决方案。我在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')
                    ;
                },
            )));
        }
    
    }
    

    【讨论】:

      【解决方案2】:

      你自己解释问题:

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

      你可以使用data transformers来解决这个问题。

      【讨论】:

      • 你好帕特。首先非常感谢您抽出时间来帮助我。给我一些时间阅读有关 Data Transformers 的文档,我会回复...
      • 嘿帕特。我必须说我现在完全迷路了。我阅读了文档,但我不明白...据您所知,还有其他更简单的解决方案吗?
      • 如果我错了,请纠正我,但您的模型数据是实体,而您的视图数据是文本(由 ajax 填充的文本框?)。因此,您提交的值格式无效(文本而不是实体)。因此,将转换器应用于“本地化”并调整 reverseTrabsform 方法。首先对您的值执行 var_dump 以确认它是一个字符串。您可以使用实体管理器并以与上述文档相同的方式转换文本。祝你好运!
      • 没有。我使用实体类型字段,因此输出位于选择标签中。这是正常的。是的,我通过 jquery 和 ajax 填充了该选择。我的问题不是字段类型,而是您提到的事实,即提交的值不包含在数组中(初始 query_buildr 查询)。所以验证器说 The value is not valid.
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-06-27
      • 1970-01-01
      • 2018-06-26
      • 2013-10-02
      • 2018-11-26
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多