我有以下代码正在运行......但我认为可以做得更好。
(下面的说明)。
Class Address
{
protected province;
public function getProvince()...
}
class AddressType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
...
$build->add(Province, new ProvinceType());
...
}
}
class ProvinceType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$provinceList = array(... //very long list
...
$build->add(Province, 'choice', array(
'choices' => $provinceList;
));
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'Acme\Bundle\Entity\Address'
));
}
}
class PersonType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$Province = array(... //very long list
...
$build->add('Address', new AddressType());
$build->add('FromProvince', new AddressType());
}
}
上面的代码有两个问题:
form_widget(person.Address.ProvinceType.ProvinceType)
才能使用它。这看起来很错误。最后,我希望能够验证有意义的字段,例如:
Acme\Bundle\Entity\Person:
property:
provinceBorn:
- NotBlank: ~ //Wish to reuse province list here for straight-forward validation.
Address:
Valid: ~
Acme\Bundle\Entity\Address:
property:
province:
- NotBlank: ~ //As well as here.
答案 0 :(得分:0)
要缩短ProvinceType
的路径,您应该将其定义为扩展Symfony的choice
类型的基本小部件(请参阅the doc)。你在这里得到的最好的就是{{ form_widget(person.address.province) }}
。
为了使选择可重复使用,将ProvinceType
提取到服务中是明智的(请参阅Symfony's doc了解如何执行此操作)并将省份列表作为参数传递到{{1我的ProvinceType
方法(将在您的包的__construct
中定义)。这样,您就可以将省份提取到外部存储中。
在验证时,请记住,您在此处提供的YAML与表单组件无关,而是与您的实体有关。因此,重复services.yml
约束实际上是有道理的,因为您没有将NotBlank
的{{1}}属性与Person
实体相关联,而是保存了一个单独的字段。< / p>
但是,如果您定义自定义字段类型,则可以通过将约束移动到您提取到服务的provinceBorn
来默认使用它。这样的约束可以这样定义:
Address
答案 1 :(得分:0)
我已经用这种方式做了类似的事情(我将使用你的例子):
Class Address
{
protected province;
public function getProvince()...
}
class AddressType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$provinceList = array(... //very long list
...
$build->add('province', 'choice', array(
'choices' => $provinceList, 'empty_value' => null, 'required' => true,
));
...
}
}
class PersonType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$Province = array(... //very long list
...
$build->add('address', new AddressType());
$build->add('fromProvince', new AddressType());
}
}
您发送数据:
...
$form = $this->createForm(new PersonType(), $entity);
return array(
'form' => $editForm->createView(),
);
如下所示在Twig中使用它:
{{ form_widget(form.address.province) }}
最后,我认为您的验证是正确的,但如果您需要更具体的内容,则可以在验证部分http://symfony.com/doc/current/book/validation.html#getters中指定Symfony文档中使用getters方法
答案 2 :(得分:0)
之前的扩展答案和解释。
继承表单 http://symfony.com/doc/current/cookbook/form/inherit_data_option.html
使用您的代码,它应该看起来像这样
class AddressType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
...
$build->add(Province, new ProvinceType(), [
'inherit_data' => true
// this is an alterrnative for having it bellow inside configure options
// use one or another, what suit you better
]);
...
}
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults([
'inherit_data' => true
]);
}
// in sf > 2.7 use public function configureOptions(OptionsResolver $resolver)
}
class ProvinceType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$provinceList = array(... //very long list
...
$build->add(Province, 'choice', array(
'choices' => $provinceList;
));
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'Acme\Bundle\Entity\Address',
'inherit_data' => true
));
}
}
class PersonType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$Province = array(... //very long list
...
$build->add('Address', new AddressType());
$build->add('FromProvince', new AddressType());
}
}
这是你的addressType从provinceType继承字段,PersonType继承自addressType(包括其从provinceType继承的字段)。
所以应该可以在模板
中做到这一点 {{ form_row(form.Province)}}
最好的方法是验证约束与Valid约束的关系。 这也会强制对孩子进行验证 http://symfony.com/doc/current/reference/constraints/Valid.html
另一个选项是在表单上设置cascade_validation,但如果有的话,这不会转发您的验证组。
无论哪种方式,您只需要在每个实体上定义一次验证。