为Symfony 2中的集合的每个项目指定不同的验证组? [英] Specify different validation groups for each item of a collection in Symfony 2?

查看:95
本文介绍了为Symfony 2中的集合的每个项目指定不同的验证组?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

[关于集合的文档]嵌入表单(集合类型)时是否可以根据当前项目为每个项目指定验证组?看来ATM不能正常工作.

[Documentation about collection] When embedding forms (collection type) is possible to specify validation groups for each item, based on the current item? It seems not working ATM.

TaskType表单添加了一个标签集合:

The TaskType form adding a collection of tags:

// 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)添加了一个新标签:

For example we have two tags (tag 1 and tag 2) and a new tag is added using the "Add" button (via JavaScript):

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

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

Tag 1 should be validated against Default, Edit groups while tag 2 against Default group only.

基于基础数据,如果标签是新标签,它将获得Default组,如果存在DefaultCreate组:

Based on the underlying data, if tag is new it gets Default group, if exists Default, Create 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实体在编辑"组中受约束

一个示例,其中Tag定义了两个属性(省略了访问器):

Tag entity with a constraint in the "Edit" group

An example with Tag defining two properties (accessors omitted):

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

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

    // ...
}

对于现有标签:说明不能为空.对于新标签:说明可以为空白.

For an existing tag: description should not be blank. For a new tag: description can be blank.

只需编辑现有标签,然后将说明保留为空白. 表单验证,但验证器服务显示错误:

Just edit an existing tag and leave the description blank. The form validates but the 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.

更新1 :我尝试使用静态方法determineValidationGroups(但未成功),如建议的此处:

Update 1: I've tried (without success) with a static method determineValidationGroups as suggested 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'
        ),
    ));
}

只有一个现有标签和一个使用添加标签"链接创建的输出看起来是正确的.但是现有标签没有错误,说明为空白:

Output with just one existing tag and one created using the "add tag" link seems correct. But no errors for the existing tag leaving the description blank:

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)

推荐答案

我用来测试答案的完整代码位于 Valid约束强制Validator验证嵌入的对象,并且AFAIK API无法提供设置验证组的方法.

Valid constraint force Validator to validate embed object, and AFAIK the API provides no way to set validation group.

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

But at a higher level, we can ask Form component to cascade ValidationListener to all embed forms, and use the Form component API to set validation group.

我们必须使用:

    在FormBuilder中的
  • 'cascade_validation' => true选项,在所有级别上.默认情况下,它设置为false.
  • TagType设置中的一个回调,用于设置验证组. (您走在正确的轨道上.)
  • 'error_bubbling' => false,因为在集合中默认情况下为
  • 'cascade_validation' => true option in the FormBuilder, at all levels. It is set to false by default.
  • a callback in TagType settings to set validation group. (You were on the right track.)
  • 'error_bubbling' => false, as it is true by default in collections

完成后,我们可以在相应字段旁边显示带有所有错误的表单.

and we're done, we can display the form with all errors next to corresponding fields.

在TaskType.php中:

in 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中:

in 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,
    ));
  }
}

这篇关于为Symfony 2中的集合的每个项目指定不同的验证组?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆