The virtual
form field option can be very useful when you have some duplicated fields in different entities.
当您在不同的实体中拥有一些重复的表单域时,虚拟表单域选项就显得非常有用。
For example, imagine you have two entities, a Company
and a Customer
:
举个例子,想象您有两个实体,Company和Customer:
Company实体:
- // src/Acme/HelloBundle/Entity/Company.php
- namespace Acme\HelloBundle\Entity;
- class Company
- {
- private $name;
- private $website;
- private $address;
- private $zipcode;
- private $city;
- private $country;
- }
Customer实体:
- // src/Acme/HelloBundle/Entity/Customer.php
- namespace Acme\HelloBundle\Entity;
- class Customer
- {
- private $firstName;
- private $lastName;
- private $address;
- private $zipcode;
- private $city;
- private $country;
- }
Like you can see, each entity shares a few of the same fields: address
, zipcode
, city
, country
.
正如您所见,每个实体都有着一些相同的表单域:address、zipcode、city和country。
Now, you want to build two forms: one for a Company
and the second for a Customer
.
现在,您要创建两个表单:一个对应Company,第二个对应Customer。
Start by creating a very simple CompanyType
and CustomerType
:
首先创建一个非常简单的CompanyType和CustomerType:
CompanyType类:
- // src/Acme/HelloBundle/Form/Type/CompanyType.php
- namespace Acme\HelloBundle\Form\Type;
- use Symfony\Component\Form\FormBuilderInterface;
- class CompanyType extends AbstractType
- {
- public function buildForm(FormBuilderInterface $builder, array $options)
- {
- $builder
- ->add('name', 'text')
- ->add('website', 'text');
- }
- }
CustomerType类:
- // src/Acme/HelloBundle/Form/Type/CustomerType.php
- namespace Acme\HelloBundle\Form\Type;
- use Symfony\Component\Form\FormBuilderInterface;
- class CustomerType extends AbstractType
- {
- public function buildForm(FormBuilderInterface $builder, array $options)
- {
- $builder
- ->add('firstName', 'text')
- ->add('lastName', 'text');
- }
- }
Now, we have to deal with the four duplicated fields. Here is a (simple) location form type:
现在我们需要处理那四个重复的表单域。下面是个(简单)的位置表单类型:
- // src/Acme/HelloBundle/Form/Type/LocationType.php
- namespace Acme\HelloBundle\Form\Type;
- use Symfony\Component\Form\FormBuilderInterface;
- use Symfony\Component\OptionsResolver\OptionsResolverInterface;
- class LocationType extends AbstractType
- {
- public function buildForm(FormBuilderInterface $builder, array $options)
- {
- $builder
- ->add('address', 'textarea')
- ->add('zipcode', 'text')
- ->add('city', 'text')
- ->add('country', 'text');
- }
- public function setDefaultOptions(OptionsResolverInterface $resolver)
- {
- $resolver->setDefaults(array(
- 'virtual' => true
- ));
- }
- public function getName()
- {
- return 'location';
- }
- }
We don't actually have a location field in each of our entities, so we can't directly link our LocationType
to our CompanyType
or CustomerType
. But we absolutely want to have a dedicated form type to deal with location (remember, DRY!).
实际上在每个实体中我们并没有location表单域,因此我们不能直接将LocationType链入我们的CompanyType或CustomerType中。但我们又绝对想要一个专门处理位置的表单类型(记住,DRY!)
The virtual
form field option is the solution.
解决这个问题就需要用到虚拟表单域选项了。
We can set the option 'virtual' => true
in the setDefaultOptions()
method of LocationType
and directly start using it in the two original form types.
我们可以在LocationType类中的
setDefaultOptions()方法中将
选项'virtual'设置为true,并且在两个原始域类型中直接使用它。
Look at the result:
所下所示:
CompanyType类:
- // CompanyType
- public function buildForm(FormBuilderInterface $builder, array $options)
- {
- $builder->add('foo', new LocationType(), array(
- 'data_class' => 'Acme\HelloBundle\Entity\Company'
- ));
- }
CustomerType类:
- // CustomerType
- public function buildForm(FormBuilderInterface $builder, array $options)
- {
- $builder->add('bar', new LocationType(), array(
- 'data_class' => 'Acme\HelloBundle\Entity\Customer'
- ));
- }
With the virtual option set to false (default behavior), the Form Component expects each underlying object to have a foo
(or bar
) property that is either some object or array which contains the four location fields. Of course, we don't have this object/array in our entities and we don't want it!
当virtual选项设为false时(缺省值),表单组件期望每个相关的对象都有一个foo(或bar)属性,要么是一些对象,要么是包含四个位置表单域的数组。当然,在我们的实体中没有这样的对象或数组,而且我们也不想那样做!
With the virtual option set to true, the Form component skips the foo
(or bar
) property, and instead "gets" and "sets" the 4 location fields directly on the underlying object!
当virtual选项设为true时,表单组件忽略foo(或bar)属性,取而代之的是在相关对象中直接"gets"和"sets"这4个位置表单域!
Instead of setting the virtual option inside LocationType , you can (just like with any options) also pass it in as an array option to the third argument of $builder->add() .如果不使用在LocationType中设置virtual选项,您也可以(如其它选项那样)将其作为一个数组选项发送到$builder->add()的第三个参数。 |