11.. index ::
2- single: Form; Virtual forms
2+ single: Form; The "inherit_data" option
33
4- How to use the Virtual Form Field Option
5- ========================================
4+ Reducing Code Duplication with "inherit_data"
5+ =============================================
66
7- The ``virtual `` form field option can be very useful when you have some
8- duplicated fields in different entities.
9-
10- For example, imagine you have two entities, a ``Company `` and a ``Customer ``::
7+ The ``inherit_data `` form field option can be very useful when you have some
8+ duplicated fields in different entities. For example, imagine you have two
9+ entities, a ``Company `` and a ``Customer ``::
1110
1211 // src/Acme/HelloBundle/Entity/Company.php
1312 namespace Acme\HelloBundle\Entity;
@@ -39,13 +38,10 @@ For example, imagine you have two entities, a ``Company`` and a ``Customer``::
3938 private $country;
4039 }
4140
42- Like you can see, each entity shares a few of the same fields: ``address ``,
41+ As you can see, each entity shares a few of the same fields: ``address ``,
4342``zipcode ``, ``city ``, ``country ``.
4443
45- Now, you want to build two forms: one for a ``Company `` and the second for
46- a ``Customer ``.
47-
48- Start by creating a very simple ``CompanyType `` and ``CustomerType ``::
44+ Let's build two forms for these entities, ``CompanyType `` and ``CustomerType ``::
4945
5046 // src/Acme/HelloBundle/Form/Type/CompanyType.php
5147 namespace Acme\HelloBundle\Form\Type;
@@ -84,8 +80,9 @@ Start by creating a very simple ``CompanyType`` and ``CustomerType``::
8480 }
8581 }
8682
87- Now, to deal with the four duplicated fields. Here is a (simple)
88- location form type::
83+ Instead of including the duplicated fields ``address ``, ``zipcode ``, ``city ``
84+ and ``country``in both of these forms, we will create a third form for that.
85+ We will call this form simply ``LocationType ``::
8986
9087 // src/Acme/HelloBundle/Form/Type/LocationType.php
9188 namespace Acme\H elloBundle\F orm\T ype;
@@ -108,7 +105,7 @@ location form type::
108105 public function setDefaultOptions(OptionsResolverInterface $resolver)
109106 {
110107 $resolver->setDefaults(array(
111- 'virtual ' => true
108+ 'inherit_data ' => true
112109 ));
113110 }
114111
@@ -118,46 +115,41 @@ location form type::
118115 }
119116 }
120117
121- You don't *actually * have a location field in each of your entities, so you
122- can't directly link ``LocationType `` to ``CompanyType `` or ``CustomerType ``.
123- But you absolutely want to have a dedicated form type to deal with location (remember, DRY!).
118+ The location form has an interesting option set, namely ``inherit_data ``. This
119+ option lets the form inherit its data from its parent form. If embedded in
120+ the company form, the fields of the location form will access the properties of
121+ the ``Company `` instance. If embedded in the customer form, the fields will
122+ access the properties of the ``Customer `` instance instead. Easy, eh?
124123
125- The `` virtual `` form field option is the solution.
124+ .. note ::
126125
127- You can set the option ``'virtual' => true `` in the ``setDefaultOptions() `` method
128- of ``LocationType `` and directly start using it in the two original form types.
126+ Instead of setting the ``inherit_data `` option inside ``LocationType ``, you
127+ can also (just like with any option) pass it in the third argument of
128+ ``$builder->add() ``.
129129
130- Look at the result ::
130+ Let's make this work by adding the location form to our two original forms ::
131131
132- // CompanyType
132+ // src/Acme/HelloBundle/Form/Type/ CompanyType.php
133133 public function buildForm(FormBuilderInterface $builder, array $options)
134134 {
135+ // ...
136+
135137 $builder->add('foo', new LocationType(), array(
136138 'data_class' => 'Acme\HelloBundle\Entity\Company'
137139 ));
138140 }
139141
140142.. code-block :: php
141143
142- // CustomerType
144+ // src/Acme/HelloBundle/Form/Type/ CustomerType.php
143145 public function buildForm(FormBuilderInterface $builder, array $options)
144146 {
147+ // ...
148+
145149 $builder->add('bar', new LocationType(), array(
146150 'data_class' => 'Acme\HelloBundle\Entity\Customer'
147151 ));
148152 }
149153
150- With the virtual option set to false (default behavior), the Form Component
151- expects each underlying object to have a ``foo `` (or ``bar ``) property that
152- is either some object or array which contains the four location fields.
153- Of course, you don't have this object/array in your entities and you don't want it!
154-
155- With the virtual option set to true, the Form component skips the ``foo `` (or ``bar ``)
156- property, and instead "gets" and "sets" the 4 location fields directly
157- on the underlying object!
158-
159- .. note ::
160-
161- Instead of setting the ``virtual `` option inside ``LocationType ``, you
162- can (just like with any options) also pass it in as an array option to
163- the third argument of ``$builder->add() ``.
154+ That's it! You have extracted duplicated field definitions to a separate
155+ location form that you can reuse wherever you need it.
0 commit comments