检查特定的validation_group在Symfony表单中是否有效?

时间:2015-11-12 22:00:21

标签: forms validation symfony

我正在构建一个复杂的symfony表单,它有点长并包含其他嵌入表单。因此,表单在UI中显示在单独的选项卡中,以使其对用户更具可读性和方便性。

因为表格很长并且在UI中分开,所以有可能在填充它时错过了某些内容,或者您​​只是插入了不正确的内容。那时验证会启动并停止保存表单。验证本身已配置完好并且运行良好。

我的问题是我有一个巨大的表单,在标签中分开,在某处有错误,我需要浏览每个标签以确切地看到什么是错误。我正在考虑使用另一种颜色制作包含错误字段的特定选项卡,这样它就可以脱颖而出,为您节省时间,想知道错误是什么以及它位于何处。

从我所看到的,我有两个选择:

  1. 使用以下内容手动检查每个标签的所有字段:
    {% if not form.children.FIELD_NAME.vars.valid %} 这将需要永远完成,我只会做它唯一可行的方式。
  2. 尝试使用validation_groups => array('Default', 'my_tab_name')并对每个标签进行逻辑分组。
  3. 我真的希望使用第二种方法,但我似乎无法弄清楚如何检查验证组,my_tab_1是否包含任何错误。我知道我可以这样做:

    $validator = $this->get('validator');
    $my_tab_1 = $validator->validate($entity, null, array('my_tab_1'));
    $my_tab_2 = $validator->validate($entity, null, array('my_tab_2'));
    $my_tab_3 = $validator->validate($entity, null, array('my_tab_3'));
    // so on
    

    但表单已经使用$form->validate()验证,并且使用此方法会触发N次更多不必要的验证。

    所以这里的问题是如何从树枝模板中检查特定验证组是否有效?如果那是不可能的,可以从Controller获取它并将其作为变量传递而不进行另一次验证吗?

    我认为我不需要发布FormType因为它们很长,嵌套并且可能只会让你感到困惑。但是,这是父表单的过度简化版本:

    class CompanyType extends AbstractType
    {
    
        public function buildForm(FormBuilderInterface $builder, array $options)
        {
            $builder
                ->add('name')
                ->add('address')
                ->add('representedBy')
                ->add('category')
                ->add('phone')
                ->add('member', new MemberType())
                ->add('contacts', new ContactType())
                ->add('notes', new NoteType())
                // and a couple more embedded form types.
            ;
        }
    
        /**
         * @param OptionsResolverInterface $resolver
         */
        public function setDefaultOptions(OptionsResolverInterface $resolver)
        {
            $resolver->setDefaults(array(
                'data_class' => 'App\FooBundle\Entity\Company',
                'cascade_validation' => true
            ));
        }
    
        /**
         * @return string
         */
        public function getName()
        {
            return 'app_company';
        }
    }
    

    如果有人有更好的想法或解决方案,我会非常感激。

1 个答案:

答案 0 :(得分:1)

首先,您可以通过两种不同的方式使用标签:

a)使用javascript。选项卡的所有内容都加载一次,可以在页面源中找到。除了一个之外,所有标签内容都是隐藏的。

b)使用链接和PHP。在这种情况下,每个标签都是另一个带有其他网址的网页。

(希望你能理解其中的差异)

我总是将第二种方法用于高级表单。因此,对于每个页面,我只添加formtype中所有表单域的一部分。对于每个页面,我也使用一个验证组。这已经足以编辑现有实体。

但问题是新的实体。您可能希望避免数据库中部分填充的实体,因此您需要验证并存储每个步骤'在会话中以及用户完成最后一步(并且验证正常)之后,您可能希望将所有表单字段一次性存储到数据库中。

此方法由craueformflowbundle使用。

要获取表单域的一部分,只需在formType中使用开关或为每个步骤创建一个formType。

namespace AppBundle\Form;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;

class CompanyType extends AbstractType
{
    /**
     * @param FormBuilderInterface $builder
     * @param array $options
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        switch ($options['flow_step']) {
            case 1:
                $builder
                    ->add('company')
                    ->add('origin')
               ;
                break;
            case 2:
                $builder
                    ->add('contactPerson', NULL, array('label' => 'Volledige naam'))
                    ->add('email', 'email', array('label' => 'Email'))
                    ->add('telephone', NULL, array('label' => 'Telefoonnummer'))
                ;
                break;
        }
    }

    /**
     * @param OptionsResolverInterface $resolver
     */
    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => 'AppBundle\Entity\Company',
            'flow_step' => 1
        ));
    }

    /**
     * @return string
     */
    public function getName()
    {
        return 'appbundle_company';
    }
}