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;
@@ -79,8 +75,9 @@ Start by creating a very simple ``CompanyType`` and ``CustomerType``::
79
75
}
80
76
}
81
77
82
- Now, to deal with the four duplicated fields. Here is a (simple)
83
- location form type::
78
+ Instead of including the duplicated fields ``address ``, ``zipcode ``, ``city ``
79
+ and ``country``in both of these forms, we will create a third form for that.
80
+ We will call this form simply ``LocationType ``::
84
81
85
82
// src/Acme/HelloBundle/Form/Type/LocationType.php
86
83
namespace Acme\H elloBundle\F orm\T ype;
@@ -102,7 +99,7 @@ location form type::
102
99
public function setDefaultOptions(OptionsResolverInterface $resolver)
103
100
{
104
101
$resolver->setDefaults(array(
105
- 'virtual ' => true
102
+ 'inherit_data ' => true
106
103
));
107
104
}
108
105
@@ -112,46 +109,41 @@ location form type::
112
109
}
113
110
}
114
111
115
- You don't *actually * have a location field in each of your entities, so you
116
- can't directly link ``LocationType `` to ``CompanyType `` or ``CustomerType ``.
117
- But you absolutely want to have a dedicated form type to deal with location (remember, DRY!).
112
+ The location form has an interesting option set, namely ``inherit_data ``. This
113
+ option lets the form inherit its data from its parent form. If embedded in
114
+ the company form, the fields of the location form will access the properties of
115
+ the ``Company `` instance. If embedded in the customer form, the fields will
116
+ access the properties of the ``Customer `` instance instead. Easy, eh?
118
117
119
- The `` virtual `` form field option is the solution.
118
+ .. note ::
120
119
121
- You can set the option ``'virtual' => true `` in the ``setDefaultOptions() `` method
122
- of ``LocationType `` and directly start using it in the two original form types.
120
+ Instead of setting the ``inherit_data `` option inside ``LocationType ``, you
121
+ can also (just like with any option) pass it in the third argument of
122
+ ``$builder->add() ``.
123
123
124
- Look at the result ::
124
+ Let's make this work by adding the location form to our two original forms ::
125
125
126
- // CompanyType
126
+ // src/Acme/HelloBundle/Form/Type/ CompanyType.php
127
127
public function buildForm(FormBuilderInterface $builder, array $options)
128
128
{
129
+ // ...
130
+
129
131
$builder->add('foo', new LocationType(), array(
130
132
'data_class' => 'Acme\HelloBundle\Entity\Company'
131
133
));
132
134
}
133
135
134
136
.. code-block :: php
135
137
136
- // CustomerType
138
+ // src/Acme/HelloBundle/Form/Type/ CustomerType.php
137
139
public function buildForm(FormBuilderInterface $builder, array $options)
138
140
{
141
+ // ...
142
+
139
143
$builder->add('bar', new LocationType(), array(
140
144
'data_class' => 'Acme\HelloBundle\Entity\Customer'
141
145
));
142
146
}
143
147
144
- With the virtual option set to false (default behavior), the Form Component
145
- expects each underlying object to have a ``foo `` (or ``bar ``) property that
146
- is either some object or array which contains the four location fields.
147
- Of course, you don't have this object/array in your entities and you don't want it!
148
-
149
- With the virtual option set to true, the Form component skips the ``foo `` (or ``bar ``)
150
- property, and instead "gets" and "sets" the 4 location fields directly
151
- on the underlying object!
152
-
153
- .. note ::
154
-
155
- Instead of setting the ``virtual `` option inside ``LocationType ``, you
156
- can (just like with any options) also pass it in as an array option to
157
- the third argument of ``$builder->add() ``.
148
+ That's it! You have extracted duplicated field definitions to a separate
149
+ location form that you can reuse wherever you need it.
0 commit comments