如何将有效约束与可为空的嵌入形式结合起来
How to combine Valid constraint with nullable embedded form
我想将验证嵌入表单(如果包含在请求有效负载中)和跳过此验证(如果不包含)的功能结合起来。
我的用例如下。
我向我的控制器发送了以下 json,包括资源 Campaign 和子资源 Article。
{
"campaign": {
"name": "New campaign",
"article": {
"title": "How to develope faster",
"summary": "This is a <b>summary</b>"
}
}
}
这是由 Symfony 表单处理的,具有以下验证:
AppBundle\Document\Campaign:
properties:
name:
- NotBlank:
message: 'campaign.validation.name.not_blank'
- Length:
min: 1
max: 300
minMessage: 'campaign.validation.name.length.min'
maxMessage: 'campaign.validation.name.length.max'
article:
- Valid: ~
AppBundle\Document\Article:
properties:
title:
- NotBlank:
message: 'article.validation.title.not_blank'
- Length:
min: 20
max: 300
minMessage: 'article.validation.title.length.min'
maxMessage: 'article.validation.title.length.max'
表格如下:
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';
}
}
所以问题是,如果我在子表单中设置了Valid约束,验证系统总是通过子资源的验证,即使它没有通过。所以这个请求会失败:
{
"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
上抛出非空白
关键是修改表单域article并在其中添加选项required 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 设置为可选但是如果我传递一个具有等于空或空属性的嵌入式 object它会自动清理。
我预计方案 2 的测试 2 会打开对标题的验证,但这不是由于空属性的清理。
我的意思是,我预料到这个结果:
- 测试 1:文章验证未开启
- 测试 2:对文章的验证打开并在 article.title
上抛出非空白
- 测试 3:对文章的验证打开并在 article.title
上抛出非空白
这种行为确实有道理,但我没想到它是默认行为,所以可能关于有效约束的文档可能更明确,或者我对这个假设的看法是错误的。
我想将验证嵌入表单(如果包含在请求有效负载中)和跳过此验证(如果不包含)的功能结合起来。
我的用例如下。
我向我的控制器发送了以下 json,包括资源 Campaign 和子资源 Article。
{
"campaign": {
"name": "New campaign",
"article": {
"title": "How to develope faster",
"summary": "This is a <b>summary</b>"
}
}
}
这是由 Symfony 表单处理的,具有以下验证:
AppBundle\Document\Campaign:
properties:
name:
- NotBlank:
message: 'campaign.validation.name.not_blank'
- Length:
min: 1
max: 300
minMessage: 'campaign.validation.name.length.min'
maxMessage: 'campaign.validation.name.length.max'
article:
- Valid: ~
AppBundle\Document\Article:
properties:
title:
- NotBlank:
message: 'article.validation.title.not_blank'
- Length:
min: 20
max: 300
minMessage: 'article.validation.title.length.min'
maxMessage: 'article.validation.title.length.max'
表格如下:
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';
}
}
所以问题是,如果我在子表单中设置了Valid约束,验证系统总是通过子资源的验证,即使它没有通过。所以这个请求会失败:
{
"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 上抛出非空白
关键是修改表单域article并在其中添加选项required 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 设置为可选但是如果我传递一个具有等于空或空属性的嵌入式 object它会自动清理。
我预计方案 2 的测试 2 会打开对标题的验证,但这不是由于空属性的清理。
我的意思是,我预料到这个结果:
- 测试 1:文章验证未开启
- 测试 2:对文章的验证打开并在 article.title 上抛出非空白
- 测试 3:对文章的验证打开并在 article.title 上抛出非空白
这种行为确实有道理,但我没想到它是默认行为,所以可能关于有效约束的文档可能更明确,或者我对这个假设的看法是错误的。