首页 文章

在Symfony 2中为集合的每个项目指定不同的验证组?

提问于
浏览
15

[Documentation about collection]当嵌入表单(集合类型)时,可以根据当前项目为每个项目指定验证组吗?它似乎不适用于ATM .

添加标签集合的 TaskType 表单:

// src/Acme/TaskBundle/Form/Type/TaskType.php

// ...
public function buildForm(FormBuilderInterface $builder, array $options)
{
    // ...

    $builder->add('tags', 'collection', array(
        // ...
        'by_reference' => false,
    ));
}

例如,我们有两个标签(标签1和标签2),并使用“添加”按钮(通过JavaScript)添加新标签:

-----------
| add tag |
-----------
- tag 1 (existing)
- tag 2 (added clicking the "add tag" button)

标签1应针对 DefaultEdit 组进行验证,而标签2仅针对 Default 组进行验证 .

定义动态验证组的TagType表单

根据基础数据,如果tag为new,则获取 Default group,如果存在 DefaultCreate groups:

// ...

public function setDefaultOptions(OptionsResolverInterface $resolver)
{
    $resolver->setDefaults(array(
        'validation_groups' => function (FormInterface $form) {
            $tag = $form->getData();

            $groups = array('Default');
            if (null !== $tag && null !== $tag->getId()) {
                $groups[] = 'Edit';
            }

            return $groups;
        }
    ));
}

// ...

在“编辑”组中具有约束的标记实体

Tag 定义两个属性的示例(省略了访问器):

class Tag
{
    /**
     * @Assert\NotBlank()
     */
    protected $name;

    /**
     * @Assert\NotBlank(groups={"Edit"})
     * @Assert\Length(max="255")
     */
    protected $description;

    // ...
}

对于 existing tag :描述不应为空 . 对于 new tag :说明可以为空 .

证明表格有效,验证员显示错误(错误!)

只需编辑现有代码并将说明留空即可 . form validates 但是 validator service shows errors

$form = $this->createForm('task', $task)
    ->handleRequest($request);

$validator = $this->get('validator');

if ($form->isValid()) {
    foreach ($task->getTags() as $tag) {
        // Validate against Default, Edit groups
        $errors = $validator->validate($tag, array('Default', 'Edit'));

        if (null !== $tag && null !== $tag->getId()) {
            echo 'Existing tag #'.$tag->getId();
        } else {
            echo 'New tag';
        }

        echo ', errors: '.count($errors).'<br>';
    }

    die('Form is valid.')

    // ...
}

输出:

Existing tag #863, errors: 1
Form is valid.

Update 1 :我已尝试使用静态方法 determineValidationGroups (未成功)here

public static function determineValidationGroups(FormInterface $form)
{
    $groups =  array('Default');
    if ($form->getData() !== null && null !== $form->getData()->getId())
    {
        $groups =  array('Edit');
    }

    var_dump($groups);

    return $groups;
}

TagType 表格中:

/**
 * {@inheritdoc}
 */
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
    $resolver->setDefaults(array(
        // ... 
        'validation_groups' => array(
            'Acme\TaskBundle\Entity\Tag',
            'determineValidationGroups'
        ),
    ));
}

仅使用一个现有标签输出,使用“添加标签”链接创建的标签似乎是正确的 . 但是现有标记没有错误,使描述留空:

array (size=1)
  0 => string 'Edit' (length=4)

array (size=1)
  0 => string 'Edit' (length=4)

rray (size=1)
  0 => string 'Default' (length=7)

rray (size=1)
  0 => string 'Default' (length=7)

1 回答

  • 12

    我用来测试我的答案的完整代码是https://github.com/guilro/SymfonyTests/tree/SO21276662 .

    Valid 约束力验证器验证嵌入对象,而AFAIK API无法设置验证组 .

    但是在更高级别,我们可以要求Form组件将ValidationListener级联到所有嵌入表单,并使用Form组件API来设置验证组 .

    我们必须使用:

    各个级别的FormBuilder中的

    • 'cascade_validation' => true 选项 . 默认设置为 false .

    • 用于设置验证组的TagType设置中的回调 . (你走在正确的轨道上 . )

    • 'error_bubbling' => false ,默认情况下在集合中为true

    我们已经完成了,我们可以在相应字段旁边显示包含所有错误的表单 .

    在TaskType.php中:

    class TaskType extends AbstractType
    {
      public function buildForm(FormBuilderInterface $builder, array $options)
      {
        $builder
            ->add('name')
            ->add('tags', 'collection', array(
                'type' => 'tag',
                'error_bubbling' => false,
                'allow_add' => true,
                'by_reference' => false,
                'cascade_validation' => true
            ))
        ;
      }
    
      public function setDefaultOptions(OptionsResolverInterface $resolver)
      {
        $resolver->setDefaults(array(
            'data_class' => 'Acme\TaskBundle\Entity\Task',
            'cascade_validation' => true
        ));
      }
    }
    

    在TagType.php中:

    class TagType extends AbstractType
    {
      public function buildForm(FormBuilderInterface $builder, array $options)
      {
        $builder
            ->add('name')
            ->add('description', 'text', array('required' => false));
      }
    
      public function setDefaultOptions(OptionsResolverInterface $resolver)
      {
        $resolver->setDefaults(array(
            'data_class' => 'Acme\TaskBundle\Entity\Tag',
            'validation_groups' => function(FormInterface $form) {
                if ($form->getData() !== null && null !== $form->getData()->getId())
                {
                    return array('Edit');
                }
                return array('Default');
            },
            'error_bubbling' => false,
        ));
      }
    }
    

相关问题