Validation 如何将有效约束与可为空的嵌入表单相结合

Validation 如何将有效约束与可为空的嵌入表单相结合,validation,symfony,symfony-forms,Validation,Symfony,Symfony Forms,我希望将验证嵌入表单(如果包含在请求负载中)的功能与跳过此验证(如果未包含)相结合 我的用例如下 我向我的控制器发送了以下json,包括资源活动和子资源文章 { "campaign": { "name": "New campaign", "article": { "title": "How to develope faster", "summary": "This is a <b>summary</b

我希望将验证嵌入表单(如果包含在请求负载中)的功能与跳过此验证(如果未包含)相结合

我的用例如下

我向我的控制器发送了以下json,包括资源活动和子资源文章

{
   "campaign": {
       "name": "New campaign",
       "article": {
           "title": "How to develope faster",
           "summary": "This is a <b>summary</b>"
       }
   }
}
表格如下所示:

class CampaignFormType extends AbstractType
{
    /**
     * {@inheritdoc}
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $transformer = new FieldToModelTransformer($options['manager'], 'slug');

        $builder
            ->add('name')
            ->add('article', new ArticleFormType());

        $builder->add(
            $builder->create('brand', 'text', [
                'invalid_message' => 'campaign.validation.brand.invalid'
            ])->addModelTransformer($transformer)
        );
    }

    /**
     * {@inheritdoc}
     */
    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => 'AppBundle\Document\Campaign',
            'csrf_protection'   => false
        ));
    }

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

class ArticleFormType extends AbstractType
{
    /**
     * {@inheritdoc}
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('title', 'text');
    }

    /**
     * {@inheritdoc}
     */
    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => 'AppBundle\Document\Article',
            'csrf_protection'   => false,
        ));
    }

    /**
     * {@inheritdoc}
     */
    public function getName()
    {
        return 'article';
    }
}
所以问题是,如果我在子表单中设置了有效的约束,验证系统总是通过子资源上的验证,即使它没有通过。因此,此请求将失败:

{
    "campaign": {
        "name": "New campaign"
    }
}
我想实现以下行为:

如果文章有效负载有数据,则验证它 如果项目为空或null,则不验证子资源 最干净的方法是什么


谢谢

所以我找到了发生的事情

我的控制器是创建表单、提交请求等的标准控制器。。。如果文章不在json中,它不会自动进行自动填充,因此在提交表单之前,它在请求中为空

我有3个用于测试场景1的数据集:

测试1:

{
    "campaign": {
        "name": "New campaign",
        "startDate": "2012-01-01",
        "endDate": "2012-02-01"
    }
}
测试2:

{
    "campaign": {
        "article": {
            "title": ""
        }
    }
}
测试3:

{
    "campaign": {
        "article": {
            "title": "",
            "summary": "Whatever valid value"
        }
    }
}
在不更改表格或验证的情况下,结果如下:

测试1:文章验证打开,并在article.title上抛出非空 测试2:文章验证打开,并在article.title上抛出非空 测试3:文章验证打开,并在article.title上抛出非空 关键是修改表单字段文章并向其中添加所需的选项false:

public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $transformer = new FieldToModelTransformer($options['manager'], 'slug');

        $builder
            ->add('name', 'text')
            ->add('article', new ArticleFormType(), [
                'required' => false
            ]);

        $builder->add(
            $builder->create('brand', 'text', [
                'invalid_message' => 'campaign.validation.brand.invalid'
            ])->addModelTransformer($transformer)
        );
    }
通过执行相同的树测试,结果为场景2:

测试1:未打开对项目的验证 测试2:即使将标题传递为空或null,文章的验证也不会打开 测试3:文章验证打开,并在article.title上抛出非空 因此,总结我需要将嵌入表单上的required false设置为可选,但如果我将属性等于empty或null的嵌入对象传递给它,它将自动清除

我希望场景2的测试2能够打开标题验证,但这并不是因为清除了null属性

我的意思是,我期待这个结果:

测试1:未打开对项目的验证 测试2:文章验证打开,并在article.title上抛出非空 测试3:文章验证打开,并在article.title上抛出非空
这种行为是有道理的,但我并不认为它是默认行为,因此,关于有效约束的文档可能更加明确,或者我对这种假设的理解可能是错误的。

验证在哪里失败?你能发布你的控制器代码吗?
public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $transformer = new FieldToModelTransformer($options['manager'], 'slug');

        $builder
            ->add('name', 'text')
            ->add('article', new ArticleFormType(), [
                'required' => false
            ]);

        $builder->add(
            $builder->create('brand', 'text', [
                'invalid_message' => 'campaign.validation.brand.invalid'
            ])->addModelTransformer($transformer)
        );
    }