diff --git a/cookbook/form/data_transformers.rst b/cookbook/form/data_transformers.rst
index 8bbcea505c1..c2ce3ae0486 100644
--- a/cookbook/form/data_transformers.rst
+++ b/cookbook/form/data_transformers.rst
@@ -28,13 +28,13 @@ Creating the Transformer
First, create an ``IssueToNumberTransformer`` class - this class will be responsible
for converting to and from the issue number and the ``Issue`` object::
- // src/Acme/TaskBundle/Form/DataTransformer/IssueToNumberTransformer.php
- namespace Acme\TaskBundle\Form\DataTransformer;
+ // src/AppBundle/Form/DataTransformer/IssueToNumberTransformer.php
+ namespace AppBundle\Form\DataTransformer;
+ use AppBundle\Entity\Issue;
+ use Doctrine\Common\Persistence\ObjectManager;
use Symfony\Component\Form\DataTransformerInterface;
use Symfony\Component\Form\Exception\TransformationFailedException;
- use Doctrine\Common\Persistence\ObjectManager;
- use Acme\TaskBundle\Entity\Issue;
class IssueToNumberTransformer implements DataTransformerInterface
{
@@ -60,7 +60,7 @@ for converting to and from the issue number and the ``Issue`` object::
public function transform($issue)
{
if (null === $issue) {
- return "";
+ return '';
}
return $issue->getNumber();
@@ -70,9 +70,7 @@ for converting to and from the issue number and the ``Issue`` object::
* Transforms a string (number) to an object (issue).
*
* @param string $number
- *
* @return Issue|null
- *
* @throws TransformationFailedException if object (issue) is not found.
*/
public function reverseTransform($number)
@@ -82,7 +80,7 @@ for converting to and from the issue number and the ``Issue`` object::
}
$issue = $this->om
- ->getRepository('AcmeTaskBundle:Issue')
+ ->getRepository('AppBundle:Issue')
->findOneBy(array('number' => $number))
;
@@ -111,29 +109,116 @@ for converting to and from the issue number and the ``Issue`` object::
Using the Transformer
---------------------
-Now that you have the transformer built, you just need to add it to your
-issue field in some form.
+As seen above our transformer requires an instance of an object manager. While for most
+use-cases it is sufficient to use the default entity manager, you will sometimes need
+to explicitly choose the one to use. To achieve this, you can use a factory::
+
+ // src/AppBundle/Form/DataTransformer/IssueToNumberTransformerFactory.php
+ namespace AppBundle\Form\DataTransformer;
+
+ use Doctrine\Common\Persistence\ManagerRegistry;
+
+ class IssueToNumberTransformerFactory
+ {
+ /**
+ * @var ManagerRegistry
+ */
+ private $registry;
+
+ public function __construct(ManagerRegistry $registry)
+ {
+ $this->registry = $registry;
+ }
+
+ public function create($om)
+ {
+ return new IssueToNumberTransformer($this->registry->getManager($om));
+ }
+ }
+
+.. configuration-block::
+
+ .. code-block:: yaml
+
+ services:
+ app.issue_transformer_factory:
+ class: AppBundle\Form\DataTransformer\IssueToNumberTransformerFactory
+ arguments: ["@doctrine"]
+ public: false
+
+ app.type.task:
+ class: AppBundle\Form\TaskType
+ arguments: ["@app.issue_transformer_factory"]
+ tag:
+ - { name: form.type, alias: app_task }
+
+ .. code-block:: xml
+
+
+
+
+
+
+
+
+
+
+ .. code-block:: php
+
+ use Symfony\Component\DependencyInjection\Definition;
+ use Symfony\Component\DependencyInjection\Reference;
+ // ...
+
+ $container
+ ->setDefinition('app.issue_transformer_factory', new Definition(
+ 'AppBundle\Form\DataTransformer\IssueToNumberTransformerFactory'
+ ), array(
+ new Reference('doctrine'),
+ ))
+ ->setPublic(false)
+ ;
+
+ $container
+ ->setDefinition('app.type.task', new Definition(
+ 'AppBundle\Form\TaskType'
+ ), array(
+ new Reference('app.issue_transformer_factory'),
+ ))
+ ->addTag('form.type', array('alias' => 'app_task'))
+ ;
+
+Now that you have the capability to build the transformer with the desired object manager, you
+just need to create it from your issue field in some form.
You can also use transformers without creating a new custom form type
by calling ``addModelTransformer`` (or ``addViewTransformer`` - see
`Model and View Transformers`_) on any field builder::
+ // src/AppBundle/Form/TaskType.php
+ namespace AppBundle\Form;
+
+ use AppBundle\Form\DataTransformer\IssueToNumberTransformerFactory;
use Symfony\Component\Form\FormBuilderInterface;
- use Acme\TaskBundle\Form\DataTransformer\IssueToNumberTransformer;
+ use Symfony\Component\OptionsResolver\OptionsResolverInterface;
class TaskType extends AbstractType
{
- public function buildForm(FormBuilderInterface $builder, array $options)
+ /**
+ * @var IssueToNumberTransformerFactory
+ */
+ private $factory;
+
+ public function __construct(IssueToNumberTransformerFactory $factory)
{
- // ...
+ $this->factory = $factory;
+ }
- // the "em" is an option that you pass when creating your form. Check out
- // the 3rd argument to createForm in the next code block to see how this
- // is passed to the form (also see setDefaultOptions).
- $entityManager = $options['em'];
- $transformer = new IssueToNumberTransformer($entityManager);
+ public function buildForm(FormBuilderInterface $builder, array $options)
+ {
+ $transformer = $this->factory->create($options['om']);
- // add a normal text field, but add your transformer to it
$builder->add(
$builder->create('issue', 'text')
->addModelTransformer($transformer)
@@ -144,27 +229,19 @@ by calling ``addModelTransformer`` (or ``addViewTransformer`` - see
{
$resolver
->setDefaults(array(
- 'data_class' => 'Acme\TaskBundle\Entity\Task',
- ))
- ->setRequired(array(
- 'em',
+ 'data_class' => 'AppBundle\Entity\Task',
))
- ->setAllowedTypes(array(
- 'em' => 'Doctrine\Common\Persistence\ObjectManager',
- ));
-
- // ...
+ ->setRequired(array('om'))
+ ;
}
-
- // ...
}
This example requires that you pass in the entity manager as an option
when creating your form. Later, you'll learn how you could create a custom
``issue`` field type to avoid needing to do this in your controller::
- $taskForm = $this->createForm(new TaskType(), $task, array(
- 'em' => $this->getDoctrine()->getManager(),
+ $taskForm = $this->createForm('app_task', $task, array(
+ 'om' => 'default',
));
Cool, you're done! Your user will be able to enter an issue number into the
@@ -254,33 +331,26 @@ a form that uses the transformer.
Because of these, you may choose to :doc:`create a custom field type `.
First, create the custom field type class::
- // src/Acme/TaskBundle/Form/Type/IssueSelectorType.php
- namespace Acme\TaskBundle\Form\Type;
+ // src/AppBundle/Form/IssueSelectorType.php
+ namespace AppBundle\Form;
+ use AppBundle\Form\DataTransformer\IssueToNumberTransformerFactory;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
- use Acme\TaskBundle\Form\DataTransformer\IssueToNumberTransformer;
- use Doctrine\Common\Persistence\ObjectManager;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
class IssueSelectorType extends AbstractType
{
- /**
- * @var ObjectManager
- */
- private $om;
-
- /**
- * @param ObjectManager $om
- */
- public function __construct(ObjectManager $om)
+ private $factory;
+
+ public function __construct(IssueToNumberTransformerFactory $factory)
{
- $this->om = $om;
+ $this->factory = $factory;
}
public function buildForm(FormBuilderInterface $builder, array $options)
{
- $transformer = new IssueToNumberTransformer($this->om);
+ $transformer = $this->factory->create($options['om']);
$builder->addModelTransformer($transformer);
}
@@ -288,6 +358,7 @@ First, create the custom field type class::
{
$resolver->setDefaults(array(
'invalid_message' => 'The selected issue does not exist',
+ 'om' => 'default'
));
}
@@ -310,24 +381,49 @@ it's recognized as a custom field type:
.. code-block:: yaml
services:
- acme_demo.type.issue_selector:
- class: Acme\TaskBundle\Form\Type\IssueSelectorType
- arguments: ["@doctrine.orm.entity_manager"]
+ app.issue_transformer_factory:
+ class: AppBundle\Form\DataTransformer\IssueToNumberTransformerFactory
+ arguments: ["@doctrine"]
+ public: false
+ app.type.issue_selector:
+ class: AppBundle\Form\IssueSelectorType
+ arguments: ["@app.issue_transformer_factory"]
tags:
- { name: form.type, alias: issue_selector }
.. code-block:: xml
-
-
+
+
+
+
+
+
.. code-block:: php
+ use Symfony\Component\DependencyInjection\Definition;
+ use Symfony\Component\DependencyInjection\Reference;
+ // ...
+
+ $container
+ ->setDefinition('app.issue_transformer_factory', new Definition(
+ 'AppBundle\Form\DataTransformer\IssueToNumberTransformerFactory'
+ ), array(
+ new Reference('doctrine'),
+ ))
+ ->setPublic(false)
+ ;
+
$container
- ->setDefinition('acme_demo.type.issue_selector', array(
- new Reference('doctrine.orm.entity_manager'),
+ ->setDefinition('app.type.issue_selector', new Definition(
+ 'AppBundle\Form\IssueSelectorType'
+ ), array(
+ new Reference('app.issue_transformer_factory'),
))
->addTag('form.type', array(
'alias' => 'issue_selector',
@@ -337,8 +433,8 @@ it's recognized as a custom field type:
Now, whenever you need to use your special ``issue_selector`` field type,
it's quite easy::
- // src/Acme/TaskBundle/Form/Type/TaskType.php
- namespace Acme\TaskBundle\Form\Type;
+ // src/AppBundle/Form/TaskType.php
+ namespace AppBundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;