[英]Symfony2: How to use constraints on custom compound form type?
Here is a question I've been breaking my head over for a while now. 这是一个我一直在讨厌的问题。 Please know that I'm not a Symfony2 expert (yet), so I might have made a rookie mistake somewhere.
请知道我还不是Symfony2专家,所以我可能在某个地方犯了一个菜鸟错误。
Field1: Standard Symfony2 text
field type Field1:标准Symfony2
text
字段类型
Field2: Custom field type compound
field with text
field + checkbox
field) Field2:自定义字段类型
compound
字段,带有text
字段+ checkbox
字段)
My Goal: Getting constraints added to the autoValue
field to work on the autoValue's text input child
我的目标:将约束添加到
autoValue
字段以处理autoValue's text input child
The reason why the constraints don't work is probably because NotBlank
is expecting a string value and the internal data of this form field is an array array('input'=>'value', 'checkbox' => true)
. 约束不起作用的原因可能是因为
NotBlank
期望一个字符串值,并且此表单字段的内部数据是一个数组array('input'=>'value', 'checkbox' => true)
。 This array value gets transformed back into a string with a custom DataTransformer
. 此数组值将转换回具有自定义
DataTransformer
的字符串。 I suspect however that that happens AFTER validating the field against known constraints. 但我怀疑在根据已知约束验证字段后会发生这种情况。
As you see below in commented code, I have been able to get constraints working on the text input, however only when hardcoded into the autoValue's form type, and I want to validate against the main field's constraints. 正如您在注释代码中看到的那样,我已经能够在文本输入上获得约束,但是只有当硬编码到autoValue的表单类型中时,我才能根据主要字段的约束进行验证。
My (simplified) sample code for controller and field: 控制器和字段的我(简化)示例代码:
. 。
Setting up a quick form for testing purposes. 设置快速表单以进行测试。
<?php
//...
// $entityInstance holds an entity that has it's own constraints
// that have been added via annotations
$formBuilder = $this->createFormBuilder( $entityInstance, array(
'attr' => array(
// added to disable html5 validation
'novalidate' => 'novalidate'
)
));
$formBuilder->add('regular_text', 'text', array(
'constraints' => array(
new \Symfony\Component\Validator\Constraints\NotBlank()
)
));
$formBuilder->add('auto_text', 'textWithAutoValue', array(
'constraints' => array(
new \Symfony\Component\Validator\Constraints\NotBlank()
)
));
. 。
src/My/Component/Form/Type/TextWithAutoValueType.php SRC /我的/分量/表/类型/ TextWithAutoValueType.php
<?php
namespace My\Component\Form\Type;
use My\Component\Form\DataTransformer\TextWithAutoValueTransformer;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
class TextWithAutoValueType extends AbstractType
{
/**
* {@inheritdoc}
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('value', 'text', array(
// when I uncomment this, the NotBlank constraint works. I just
// want to validate against whatever constraints are added to the
// main form field 'auto_text' instead of hardcoding them here
// 'constraints' => array(
// new \Symfony\Component\Validator\Constraints\NotBlank()
// )
));
$builder->add('checkbox', 'checkbox', array(
));
$builder->addModelTransformer(
new TextWithAutoValueTransformer()
);
}
public function getName()
{
return 'textWithAutoValue';
}
}
src/My/Component/Form/DataTransformer/TextWithAutoValueType.php SRC /我的/分量/表格/ DataTransformer / TextWithAutoValueType.php
<?php
namespace My\Component\Form\DataTransformer;
use Symfony\Component\Form\DataTransformerInterface;
class TextWithAutoValueTransformer
implements DataTransformerInterface
{
/**
* @inheritdoc
*/
public function transform($value)
{
return array(
'value' => (string) $value,
'checkbox' => true
);
}
/**
* @inheritdoc
*/
public function reverseTransform($value)
{
return $value['value'];
}
}
src/My/ComponentBundle/Resources/config/services.yml SRC /我的/ ComponentBundle /资源/配置/ services.yml
parameters:
services:
my_component.form.type.textWithAutoValue:
class: My\Component\Form\Type\TextWithAutoValueType
tags:
- { name: form.type, alias: textWithAutoValue }
src/My/ComponentBundle/Resources/views/Form/fields.html.twig SRC /我的/ ComponentBundle /资源/视图/表格/ fields.html.twig
{% block textWithAutoValue_widget %}
{% spaceless %}
{{ form_widget(form.value) }}
{{ form_widget(form.checkbox) }}
<label for="{{ form.checkbox.vars.id}}">use default value</label>
{% endspaceless %}
{% endblock %}
. 。
I have been reading docs and google for quite some hours now and can't figure out how to copy, bind, or reference the original constraints that have been added while building this form. 我一直在阅读docs和google几个小时,无法弄清楚如何复制,绑定或引用构建此表单时添加的原始约束。
-> Does anyone know how to accomplish this? - >有谁知道怎么做到这一点?
-> For bonus points; - >奖励积分; how to enable the constraints that have been added to the main form's bound entity?
如何启用已添加到主窗体绑定实体的约束? (via annotations on the entity class)
(通过实体类的注释)
PS PS
Sorry it became such a long question, I hope that I succeeded in making my issue clear. 对不起它成了这么长的问题,我希望我成功地解决了我的问题。 If not, please ask me for more details!
如果没有,请向我询问更多详情!
I suggest you read again the documentation about validation first. 我建议您先阅读有关验证的文档 。
What we can make out of this is that validation primarily occurs on classes rather than form types. 我们可以做到的是验证主要发生在类而不是表单类型上。 That is what you overlooked.
那是你忽略的。 What you need to do is:
你需要做的是:
validation.yml : validation.yml :
src/My/Bundle/Form/Model/TextWithAutoValue:
properties:
text:
- Type:
type: string
- NotBlank: ~
checkbox:
- Type:
type: boolean
Edit: 编辑:
I assume that you already know how to use a form type in another. 我假设您已经知道如何在另一个表单中使用表单类型。 When defining your validation configuration, you can use a very useful something, called validation groups .
定义验证配置时,您可以使用一个非常有用的东西,称为验证组 。 Here a basic example (in a validation.yml file, since I'm not much proficient with validation annotations):
这是一个基本的例子(在validation.yml文件中,因为我不太熟悉验证注释):
src/My/Bundle/Form/Model/TextWithAutoValue:
properties:
text:
- Type:
type: string
groups: [ Default, Create, Edit ]
- NotBlank:
groups: [ Edit ]
checkbox:
- Type:
type: boolean
There is a groups parameter that can be added to every constraint. 有一个groups参数可以添加到每个约束。 It is an array containing validation group names.
它是一个包含验证组名称的数组。 When requesting a validation on an object, you can specify with which set of groups you want to validate.
请求对对象进行验证时,您可以指定要验证的组集。 The system will then look in the validation file what constraints should be applied.
然后,系统将在验证文件中查找应该应用的约束。
By default, the "Default" group is set on all constraints. 默认情况下,“默认”组在所有约束上设置。 This also is the group that is used when performing a regular validation.
这也是执行常规验证时使用的组。
This, of course, is the standard behaviour for all form type options. 当然,这是所有表单类型选项的标准行为。 An example:
一个例子:
$formBuilder->add('auto_text', 'textWithAutoValue', array(
'label' => 'my_label',
'validation_groups' => array('Default', 'Edit'),
));
As for the use of different entities, you can pile up your data classes following the same architecture than your piled-up forms. 至于使用不同的实体,您可以使用与堆积形式相同的架构来堆积数据类。 In the example above, a form type using textWithAutoValueType will have to have a data_class that has a 'auto_text' property and the corresponding getter/setter.
在上面的示例中,使用textWithAutoValueType的表单类型必须具有data_class,该data_class具有'auto_text'属性和相应的getter / setter。
In the validation file, the Valid constraints will be able to cascade validation. 在验证文件中, 有效约束将能够级联验证。 A property with Valid will detect the class of the property and will try to find a corresponding validation configuration for this class, and apply it with the same validation groups:
具有Valid的属性将检测属性的类,并将尝试为此类查找相应的验证配置,并将其应用于相同的验证组:
src/My/Bundle/Form/Model/ContainerDataClass:
properties:
auto_text:
Valid: ~ # Will call the validation conf just below with the same groups
src/My/Bundle/Form/Model/TextWithAutoValue:
properties:
... etc
As described here https://speakerdeck.com/bschussek/3-steps-to-symfony2-form-mastery#39 (slide 39) by Bernhard Schussek (the main contributor of symofny form extension), a transformer should never change the information, but only change its representation. 如下所述https://speakerdeck.com/bschussek/3-steps-to-symfony2-form-mastery#39 (幻灯片39)由Bernhard Schussek(symofny表格扩展的主要贡献者),变压器应该永远不会改变信息,但只改变其代表性。
Adding the information (checkbox' => true), you are doing something wrong. 添加信息(复选框'=> true),你做错了什么。
In Edit: 在编辑中:
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('value', 'text', $options);
$builder->add('checkbox', 'checkbox', array('mapped'=>false));
$builder->addModelTransformer(
new TextWithAutoValueTransformer()
);
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.