1
1
.. index ::
2
- single: Form; Virtual forms
2
+ single: Form; The "inherit_data" option
3
3
4
- How to use the Virtual Form Field Option
5
- ========================================
4
+ Reducing Code Duplication with "inherit_data"
5
+ =============================================
6
6
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 ``::
11
10
12
11
// src/Acme/HelloBundle/Entity/Company.php
13
12
namespace Acme\HelloBundle\Entity;
@@ -39,13 +38,10 @@ For example, imagine you have two entities, a ``Company`` and a ``Customer``::
39
38
private $country;
40
39
}
41
40
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 ``,
43
42
``zipcode ``, ``city ``, ``country ``.
44
43
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 ``::
49
45
50
46
// src/Acme/HelloBundle/Form/Type/CompanyType.php
51
47
namespace Acme\HelloBundle\Form\Type;
@@ -84,8 +80,9 @@ Start by creating a very simple ``CompanyType`` and ``CustomerType``::
84
80
}
85
81
}
86
82
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 ``::
89
86
90
87
// src/Acme/HelloBundle/Form/Type/LocationType.php
91
88
namespace Acme\H elloBundle\F orm\T ype;
@@ -108,7 +105,7 @@ location form type::
108
105
public function setDefaultOptions(OptionsResolverInterface $resolver)
109
106
{
110
107
$resolver->setDefaults(array(
111
- 'virtual ' => true
108
+ 'inherit_data ' => true
112
109
));
113
110
}
114
111
@@ -118,46 +115,41 @@ location form type::
118
115
}
119
116
}
120
117
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?
124
123
125
- The `` virtual `` form field option is the solution.
124
+ .. note ::
126
125
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() ``.
129
129
130
- Look at the result ::
130
+ Let's make this work by adding the location form to our two original forms ::
131
131
132
- // CompanyType
132
+ // src/Acme/HelloBundle/Form/Type/ CompanyType.php
133
133
public function buildForm(FormBuilderInterface $builder, array $options)
134
134
{
135
+ // ...
136
+
135
137
$builder->add('foo', new LocationType(), array(
136
138
'data_class' => 'Acme\HelloBundle\Entity\Company'
137
139
));
138
140
}
139
141
140
142
.. code-block :: php
141
143
142
- // CustomerType
144
+ // src/Acme/HelloBundle/Form/Type/ CustomerType.php
143
145
public function buildForm(FormBuilderInterface $builder, array $options)
144
146
{
147
+ // ...
148
+
145
149
$builder->add('bar', new LocationType(), array(
146
150
'data_class' => 'Acme\HelloBundle\Entity\Customer'
147
151
));
148
152
}
149
153
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