Skip to content

Update data_transformers.rst #5307

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Jun 27, 2015
Merged
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
130 changes: 94 additions & 36 deletions cookbook/form/data_transformers.rst
Original file line number Diff line number Diff line change
Expand Up @@ -111,29 +111,100 @@ 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 using the default manager is fine we will let you pick the manager by it's name.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[...] is fine, we will [...]

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We avoid the first person perspective in the docs. So we should reword the sentence a bit like the following:

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::

In order to achieve this we will add a factory::

// src/Acme/TaskBundle/Form/DataTransformer/IssueToNumberTransformerFactory.php
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's use the AppBundle here.

namespace Acme\TaskBundle\Form\DataTransformer;

use Symfony\Bridge\Doctrine\ManagerRegistry;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do you have any reason why you don't use Doctrine\Common\Persistence\ManagerRegistry, but require the specific bridge implementation?


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:
acme_demo.factory.issue_transformer:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Imho "factory" should be reflected in the service id.

class: Acme\TaskBundle\Form\DataTransformer\IssueToNumberTransformerFactory
arguments: ["@doctrine"]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can make the transformer factory private.


acme_demo.type.task:
class: Acme\TaskBundle\Form\TaskType
arguments: ["@acme_demo.factory.issue_transformer"]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need to tag this as a form type:

tag:
    - { name: form.type, alias: app_task }


.. code-block:: xml

<service id="acme_demo.factory.issue_transformer" class="Acme\TaskBundle\Form\DataTransformer\IssueToNumberTransformerFactory">
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you should add the class attribute on a new line, to prevent horizontal scrolling (same below):

<service id="app.factory.issue_transformer"
    class="AppBundle\Form\DataTransformer\IssueToNumberTransformerFactory">

<argument type="service" id="doctrine"/>
</service>

<service id="acme_demo.type.task" class="Acme\TaskBundle\Form\DataTransformer\IssueToNumberTransformerFactory">
<argument type="service" id="acme_demo.factory.issue_transformer"/>
</service>

.. code-block:: php

$container
->setDefinition('acme_demo.factory.issue_transformer', array(
new Reference('doctrine'),
))
;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is invalid (same below). It should be something like:

use Symfony\Component\DependencyInjection\Definition;
use Symfony\Component\DependencyInjection\Reference;
// ...

$definition = new Definition(
    'AppBundle\Form\DataTransformer\IssueToNumberTransformerFactory',
    array(new Reference('doctrine'))
);
$container->setDefinition('app.factory.issue_transformer', $definition);


$container
->setDefinition('acme_demo.type.task', array(
new Reference('acme_demo.factory.issue_transformer'),
))
;

Now that you have capability to build the transformer with the desired object manager, you
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"Now that you have the capability [...]"

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/Acme/TaskBundle/Form/TaskType.php
namespace Acme\TaskBundle\Form;

use Acme\TaskBundle\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)
Expand All @@ -146,25 +217,18 @@ by calling ``addModelTransformer`` (or ``addViewTransformer`` - see
->setDefaults(array(
'data_class' => 'Acme\TaskBundle\Entity\Task',
))
->setRequired(array(
'em',
))
->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(),
$taskType = $this->get('acme_demo.type.task');
$taskForm = $this->createForm($taskType, $task, array(
'om' => 'default',
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This can just be:

$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
Expand Down Expand Up @@ -257,37 +321,31 @@ First, create the custom field type class::
// src/Acme/TaskBundle/Form/Type/IssueSelectorType.php
namespace Acme\TaskBundle\Form\Type;

use Acme\TaskBundle\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);
}

public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'invalid_message' => 'The selected issue does not exist',
'om' => 'default'
));
}

Expand Down