@@ -28,13 +28,13 @@ Creating the Transformer
28
28
First, create an ``IssueToNumberTransformer `` class - this class will be responsible
29
29
for converting to and from the issue number and the ``Issue `` object::
30
30
31
- // src/Acme/TaskBundle /Form/DataTransformer/IssueToNumberTransformer.php
32
- namespace Acme\TaskBundle \Form\DataTransformer;
31
+ // src/AppBundle /Form/DataTransformer/IssueToNumberTransformer.php
32
+ namespace AppBundle \Form\DataTransformer;
33
33
34
+ use AppBundle\Entity\Issue;
35
+ use Doctrine\Common\Persistence\ObjectManager;
34
36
use Symfony\Component\Form\DataTransformerInterface;
35
37
use Symfony\Component\Form\Exception\TransformationFailedException;
36
- use Doctrine\Common\Persistence\ObjectManager;
37
- use Acme\TaskBundle\Entity\Issue;
38
38
39
39
class IssueToNumberTransformer implements DataTransformerInterface
40
40
{
@@ -60,7 +60,7 @@ for converting to and from the issue number and the ``Issue`` object::
60
60
public function transform($issue)
61
61
{
62
62
if (null === $issue) {
63
- return "" ;
63
+ return '' ;
64
64
}
65
65
66
66
return $issue->getNumber();
@@ -70,9 +70,7 @@ for converting to and from the issue number and the ``Issue`` object::
70
70
* Transforms a string (number) to an object (issue).
71
71
*
72
72
* @param string $number
73
- *
74
73
* @return Issue|null
75
- *
76
74
* @throws TransformationFailedException if object (issue) is not found.
77
75
*/
78
76
public function reverseTransform($number)
@@ -82,7 +80,7 @@ for converting to and from the issue number and the ``Issue`` object::
82
80
}
83
81
84
82
$issue = $this->om
85
- ->getRepository('AcmeTaskBundle :Issue')
83
+ ->getRepository('AppBundle :Issue')
86
84
->findOneBy(array('number' => $number))
87
85
;
88
86
@@ -111,29 +109,116 @@ for converting to and from the issue number and the ``Issue`` object::
111
109
Using the Transformer
112
110
---------------------
113
111
114
- Now that you have the transformer built, you just need to add it to your
115
- issue field in some form.
112
+ As seen above our transformer requires an instance of an object manager. While for most
113
+ use-cases it is sufficient to use the default entity manager, you will sometimes need
114
+ to explicitly choose the one to use. To achieve this, you can use a factory::
115
+
116
+ // src/AppBundle/Form/DataTransformer/IssueToNumberTransformerFactory.php
117
+ namespace AppBundle\Form\DataTransformer;
118
+
119
+ use Doctrine\Common\Persistence\ManagerRegistry;
120
+
121
+ class IssueToNumberTransformerFactory
122
+ {
123
+ /**
124
+ * @var ManagerRegistry
125
+ */
126
+ private $registry;
127
+
128
+ public function __construct(ManagerRegistry $registry)
129
+ {
130
+ $this->registry = $registry;
131
+ }
132
+
133
+ public function create($om)
134
+ {
135
+ return new IssueToNumberTransformer($this->registry->getManager($om));
136
+ }
137
+ }
138
+
139
+ .. configuration-block ::
140
+
141
+ .. code-block :: yaml
142
+
143
+ services :
144
+ app.issue_transformer_factory :
145
+ class : AppBundle\Form\DataTransformer\IssueToNumberTransformerFactory
146
+ arguments : ["@doctrine"]
147
+ public : false
148
+
149
+ app.type.task :
150
+ class : AppBundle\Form\TaskType
151
+ arguments : ["@app.issue_transformer_factory"]
152
+ tag :
153
+ - { name: form.type, alias: app_task }
154
+
155
+ .. code-block :: xml
156
+
157
+ <service id =" app.issue_transformer_factory"
158
+ class =" AppBundle\Form\DataTransformer\IssueToNumberTransformerFactory" public =" false" >
159
+ <argument type =" service" id =" doctrine" />
160
+ </service >
161
+
162
+ <service id =" app.type.task"
163
+ class =" AppBundle\Form\TaskType" >
164
+ <argument type =" service" id =" app.issue_transformer_factory" />
165
+ <tag name =" form.type" alias =" app_task" />
166
+ </service >
167
+
168
+ .. code-block :: php
169
+
170
+ use Symfony\Component\DependencyInjection\Definition;
171
+ use Symfony\Component\DependencyInjection\Reference;
172
+ // ...
173
+
174
+ $container
175
+ ->setDefinition('app.issue_transformer_factory', new Definition(
176
+ 'AppBundle\Form\DataTransformer\IssueToNumberTransformerFactory'
177
+ ), array(
178
+ new Reference('doctrine'),
179
+ ))
180
+ ->setPublic(false)
181
+ ;
182
+
183
+ $container
184
+ ->setDefinition('app.type.task', new Definition(
185
+ 'AppBundle\Form\TaskType'
186
+ ), array(
187
+ new Reference('app.issue_transformer_factory'),
188
+ ))
189
+ ->addTag('form.type', array('alias' => 'app_task'))
190
+ ;
191
+
192
+ Now that you have the capability to build the transformer with the desired object manager, you
193
+ just need to create it from your issue field in some form.
116
194
117
195
You can also use transformers without creating a new custom form type
118
196
by calling ``addModelTransformer `` (or ``addViewTransformer `` - see
119
197
`Model and View Transformers `_) on any field builder::
120
198
199
+ // src/AppBundle/Form/TaskType.php
200
+ namespace AppBundle\Form;
201
+
202
+ use AppBundle\Form\DataTransformer\IssueToNumberTransformerFactory;
121
203
use Symfony\Component\Form\FormBuilderInterface;
122
- use Acme\TaskBundle\Form\DataTransformer\IssueToNumberTransformer ;
204
+ use Symfony\Component\OptionsResolver\OptionsResolverInterface ;
123
205
124
206
class TaskType extends AbstractType
125
207
{
126
- public function buildForm(FormBuilderInterface $builder, array $options)
208
+ /**
209
+ * @var IssueToNumberTransformerFactory
210
+ */
211
+ private $factory;
212
+
213
+ public function __construct(IssueToNumberTransformerFactory $factory)
127
214
{
128
- // ...
215
+ $this->factory = $factory;
216
+ }
129
217
130
- // the "em" is an option that you pass when creating your form. Check out
131
- // the 3rd argument to createForm in the next code block to see how this
132
- // is passed to the form (also see setDefaultOptions).
133
- $entityManager = $options['em'];
134
- $transformer = new IssueToNumberTransformer($entityManager);
218
+ public function buildForm(FormBuilderInterface $builder, array $options)
219
+ {
220
+ $transformer = $this->factory->create($options['om']);
135
221
136
- // add a normal text field, but add your transformer to it
137
222
$builder->add(
138
223
$builder->create('issue', 'text')
139
224
->addModelTransformer($transformer)
@@ -144,27 +229,19 @@ by calling ``addModelTransformer`` (or ``addViewTransformer`` - see
144
229
{
145
230
$resolver
146
231
->setDefaults(array(
147
- 'data_class' => 'Acme\TaskBundle\Entity\Task',
148
- ))
149
- ->setRequired(array(
150
- 'em',
232
+ 'data_class' => 'AppBundle\Entity\Task',
151
233
))
152
- ->setAllowedTypes(array(
153
- 'em' => 'Doctrine\Common\Persistence\ObjectManager',
154
- ));
155
-
156
- // ...
234
+ ->setRequired(array('om'))
235
+ ;
157
236
}
158
-
159
- // ...
160
237
}
161
238
162
239
This example requires that you pass in the entity manager as an option
163
240
when creating your form. Later, you'll learn how you could create a custom
164
241
``issue `` field type to avoid needing to do this in your controller::
165
242
166
- $taskForm = $this->createForm(new TaskType() , $task, array(
167
- 'em ' => $this->getDoctrine()->getManager() ,
243
+ $taskForm = $this->createForm('app_task' , $task, array(
244
+ 'om ' => 'default' ,
168
245
));
169
246
170
247
Cool, you're done! Your user will be able to enter an issue number into the
@@ -254,40 +331,34 @@ a form that uses the transformer.
254
331
Because of these, you may choose to :doc: `create a custom field type </cookbook/form/create_custom_field_type >`.
255
332
First, create the custom field type class::
256
333
257
- // src/Acme/TaskBundle/ Form/Type /IssueSelectorType.php
258
- namespace Acme\TaskBundle\ Form\Type ;
334
+ // src/AppBundle/ Form/IssueSelectorType.php
335
+ namespace AppBundle\ Form;
259
336
337
+ use AppBundle\Form\DataTransformer\IssueToNumberTransformerFactory;
260
338
use Symfony\Component\Form\AbstractType;
261
339
use Symfony\Component\Form\FormBuilderInterface;
262
- use Acme\TaskBundle\Form\DataTransformer\IssueToNumberTransformer;
263
- use Doctrine\Common\Persistence\ObjectManager;
264
340
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
265
341
266
342
class IssueSelectorType extends AbstractType
267
343
{
268
- /**
269
- * @var ObjectManager
270
- */
271
- private $om;
272
-
273
- /**
274
- * @param ObjectManager $om
275
- */
276
- public function __construct(ObjectManager $om)
344
+ private $factory;
345
+
346
+ public function __construct(IssueToNumberTransformerFactory $factory)
277
347
{
278
- $this->om = $om ;
348
+ $this->factory = $factory ;
279
349
}
280
350
281
351
public function buildForm(FormBuilderInterface $builder, array $options)
282
352
{
283
- $transformer = new IssueToNumberTransformer( $this->om );
353
+ $transformer = $this->factory->create($options['om'] );
284
354
$builder->addModelTransformer($transformer);
285
355
}
286
356
287
357
public function setDefaultOptions(OptionsResolverInterface $resolver)
288
358
{
289
359
$resolver->setDefaults(array(
290
360
'invalid_message' => 'The selected issue does not exist',
361
+ 'om' => 'default'
291
362
));
292
363
}
293
364
@@ -310,24 +381,49 @@ it's recognized as a custom field type:
310
381
.. code-block :: yaml
311
382
312
383
services :
313
- acme_demo.type.issue_selector :
314
- class : Acme\TaskBundle\Form\Type\IssueSelectorType
315
- arguments : ["@doctrine.orm.entity_manager"]
384
+ app.issue_transformer_factory :
385
+ class : AppBundle\Form\DataTransformer\IssueToNumberTransformerFactory
386
+ arguments : ["@doctrine"]
387
+ public : false
388
+ app.type.issue_selector :
389
+ class : AppBundle\Form\IssueSelectorType
390
+ arguments : ["@app.issue_transformer_factory"]
316
391
tags :
317
392
- { name: form.type, alias: issue_selector }
318
393
319
394
.. code-block :: xml
320
395
321
- <service id =" acme_demo.type.issue_selector" class =" Acme\TaskBundle\Form\Type\IssueSelectorType" >
322
- <argument type =" service" id =" doctrine.orm.entity_manager" />
396
+ <service id =" app.issue_transformer_factory"
397
+ class =" AppBundle\Form\DataTransformer\IssueToNumberTransformerFactory" public =" false" >
398
+ <argument type =" service" id =" doctrine" />
399
+ </service >
400
+
401
+ <service id =" app.type.issue_selector"
402
+ class =" AppBundle\Form\IssueSelectorType" >
403
+ <argument type =" service" id =" app.issue_transformer_factory" />
323
404
<tag name =" form.type" alias =" issue_selector" />
324
405
</service >
325
406
326
407
.. code-block :: php
327
408
409
+ use Symfony\Component\DependencyInjection\Definition;
410
+ use Symfony\Component\DependencyInjection\Reference;
411
+ // ...
412
+
413
+ $container
414
+ ->setDefinition('app.issue_transformer_factory', new Definition(
415
+ 'AppBundle\Form\DataTransformer\IssueToNumberTransformerFactory'
416
+ ), array(
417
+ new Reference('doctrine'),
418
+ ))
419
+ ->setPublic(false)
420
+ ;
421
+
328
422
$container
329
- ->setDefinition('acme_demo.type.issue_selector', array(
330
- new Reference('doctrine.orm.entity_manager'),
423
+ ->setDefinition('app.type.issue_selector', new Definition(
424
+ 'AppBundle\Form\IssueSelectorType'
425
+ ), array(
426
+ new Reference('app.issue_transformer_factory'),
331
427
))
332
428
->addTag('form.type', array(
333
429
'alias' => 'issue_selector',
@@ -337,8 +433,8 @@ it's recognized as a custom field type:
337
433
Now, whenever you need to use your special ``issue_selector `` field type,
338
434
it's quite easy::
339
435
340
- // src/Acme/TaskBundle/ Form/Type /TaskType.php
341
- namespace Acme\TaskBundle\ Form\Type ;
436
+ // src/AppBundle/ Form/TaskType.php
437
+ namespace AppBundle\ Form;
342
438
343
439
use Symfony\Component\Form\AbstractType;
344
440
use Symfony\Component\Form\FormBuilderInterface;
0 commit comments