8000 feature #5307 Update data_transformers.rst (zebba) · kbond/symfony-docs@c3b43b6 · GitHub
[go: up one dir, main page]

Skip to content

Commit c3b43b6

Browse files
committed
feature symfony#5307 Update data_transformers.rst (zebba)
This PR was merged into the 2.3 branch. Discussion ---------- Update data_transformers.rst | Q | A | ------------- | --- | Doc fix? | yes | New docs? | no | Applies to | 2.3+ | Fixed tickets | symfony#2471 Commits ------- 939cfc5 Update data_transformers.rst 4b09b3f Update data_transformers.rst 7929ed5 Update data_transformers.rst 19324e8 Update data_transformers.rst
2 parents 5467a56 + 939cfc5 commit c3b43b6

File tree

1 file changed

+152
-56
lines changed

1 file changed

+152
-56
lines changed

cookbook/form/data_transformers.rst

Lines changed: 152 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -28,13 +28,13 @@ Creating the Transformer
2828
First, create an ``IssueToNumberTransformer`` class - this class will be responsible
2929
for converting to and from the issue number and the ``Issue`` object::
3030

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;
3333

34+
use AppBundle\Entity\Issue;
35+
use Doctrine\Common\Persistence\ObjectManager;
3436
use Symfony\Component\Form\DataTransformerInterface;
3537
use Symfony\Component\Form\Exception\TransformationFailedException;
36-
use Doctrine\Common\Persistence\ObjectManager;
37-
use Acme\TaskBundle\Entity\Issue;
3838

3939
class IssueToNumberTransformer implements DataTransformerInterface
4040
{
@@ -60,7 +60,7 @@ for converting to and from the issue number and the ``Issue`` object::
6060
public function transform($issue)
6161
{
6262
if (null === $issue) {
63-
return "";
63+
return '';
6464
}
6565

6666
return $issue->getNumber();
@@ -70,9 +70,7 @@ for converting to and from the issue number and the ``Issue`` object::
7070
* Transforms a string (number) to an object (issue).
7171
*
7272
* @param string $number
73-
*
7473
* @return Issue|null
75-
*
7674
* @throws TransformationFailedException if object (issue) is not found.
7775
*/
7876
public function reverseTransform($number)
@@ -82,7 +80,7 @@ for converting to and from the issue number and the ``Issue`` object::
8280
}
8381

8482
$issue = $this->om
85-
->getRepository('AcmeTaskBundle:Issue')
83+
->getRepository('AppBundle:Issue')
8684
->findOneBy(array('number' => $number))
8785
;
8886

@@ -111,29 +109,116 @@ for converting to and from the issue number and the ``Issue`` object::
111109
Using the Transformer
112110
---------------------
113111

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.
116194

117195
You can also use transformers without creating a new custom form type
118196
by calling ``addModelTransformer`` (or ``addViewTransformer`` - see
119197
`Model and View Transformers`_) on any field builder::
120198

199+
// src/AppBundle/Form/TaskType.php
200+
namespace AppBundle\Form;
201+
202+
use AppBundle\Form\DataTransformer\IssueToNumberTransformerFactory;
121203
use Symfony\Component\Form\FormBuilderInterface;
122-
use Acme\TaskBundle\Form\DataTransformer\IssueToNumberTransformer;
204+
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
123205

124206
class TaskType extends AbstractType
125207
{
126-
public function buildForm(FormBuilderInterface $builder, array $options)
208+
/**
209+
* @var IssueToNumberTransformerFactory
210+
*/
211+
private $factory;
212+
213+
public function __construct(IssueToNumberTransformerFactory $factory)
127214
{
128-
// ...
215+
$this->factory = $factory;
216+
}
129217

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']);
135221

136-
// add a normal text field, but add your transformer to it
137222
$builder->add(
138223
$builder->create('issue', 'text')
139224
->addModelTransformer($transformer)
@@ -144,27 +229,19 @@ by calling ``addModelTransformer`` (or ``addViewTransformer`` - see
144229
{
145230
$resolver
146231
->setDefaults(array(
147-
'data_class' => 'Acme\TaskBundle\Entity\Task',
148-
))
149-
->setRequired(array(
150-
'em',
232+
'data_class' => 'AppBundle\Entity\Task',
151233
))
152-
->setAllowedTypes(array(
153-
'em' => 'Doctrine\Common\Persistence\ObjectManager',
154-
));
155-
156-
// ...
234+
->setRequired(array('om'))
235+
;
157236
}
158-
159-
// ...
160237
}
161238

162239
This example requires that you pass in the entity manager as an option
163240
when creating your form. Later, you'll learn how you could create a custom
164241
``issue`` field type to avoid needing to do this in your controller::
165242

166-
$taskForm = $this->createForm(new TaskType(), $task, array(
167-
'em' => $this->getDoctrine()->getManager(),
243+
$taskForm = $this->createForm('app_task', $task, array(
244+
'om' => 'default',
168245
));
169246

170247
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.
254331
Because of these, you may choose to :doc:`create a custom field type </cookbook/form/create_custom_field_type>`.
255332
First, create the custom field type class::
256333

257-
// src/Acme/TaskBundle/Form/Type/IssueSelectorType.php
258-
namespace Acme\TaskBundle\Form\Type;
334+
// src/AppBundle/Form/IssueSelectorType.php
335+
namespace AppBundle\Form;
259336

337+
use AppBundle\Form\DataTransformer\IssueToNumberTransformerFactory;
260338
use Symfony\Component\Form\AbstractType;
261339
use Symfony\Component\Form\FormBuilderInterface;
262-
use Acme\TaskBundle\Form\DataTransformer\IssueToNumberTransformer;
263-
use Doctrine\Common\Persistence\ObjectManager;
264340
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
265341

266342
class IssueSelectorType extends AbstractType
267343
{
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)
277347
{
278-
$this->om = $om;
348+
$this->factory = $factory;
279349
}
280350

281351
public function buildForm(FormBuilderInterface $builder, array $options)
282352
{
283-
$transformer = new IssueToNumberTransformer($this->om);
353+
$transformer = $this->factory->create($options['om']);
284354
$builder->addModelTransformer($transformer);
285355
}
286356

287357
public function setDefaultOptions(OptionsResolverInterface $resolver)
288358
{
289359
$resolver->setDefaults(array(
290360
'invalid_message' => 'The selected issue does not exist',
361+
'om' => 'default'
291362
));
292363
}
293364

@@ -310,24 +381,49 @@ it's recognized as a custom field type:
310381
.. code-block:: yaml
311382
312383
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"]
316391
tags:
317392
- { name: form.type, alias: issue_selector }
318393
319394
.. code-block:: xml
320395
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"/>
323404
<tag name="form.type" alias="issue_selector" />
324405
</service>
325406
326407
.. code-block:: php
327408
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+
328422
$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'),
331427
))
332428
->addTag('form.type', array(
333429
'alias' => 'issue_selector',
@@ -337,8 +433,8 @@ it's recognized as a custom field type:
337433
Now, whenever you need to use your special ``issue_selector`` field type,
338434
it's quite easy::
339435

340-
// src/Acme/TaskBundle/Form/Type/TaskType.php
341-
namespace Acme\TaskBundle\Form\Type;
436+
// src/AppBundle/Form/TaskType.php
437+
namespace AppBundle\Form;
342438

343439
use Symfony\Component\Form\AbstractType;
344440
use Symfony\Component\Form\FormBuilderInterface;

0 commit comments

Comments
 (0)
0