-
-
Notifications
You must be signed in to change notification settings - Fork 5.2k
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
Update data_transformers.rst #5307
Merged
Merged
Changes from all commits
Commits
Show all changes
4 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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 | ||
|
||
<service id="app.issue_transformer_factory" | ||
class="AppBundle\Form\DataTransformer\IssueToNumberTransformerFactory" public="false"> | ||
<argument type="service" id="doctrine"/> | ||
</service> | ||
|
||
<service id="app.type.task" | ||
class="AppBundle\Form\TaskType"> | ||
<argument type="service" id="app.issue_transformer_factory"/> | ||
<tag name="form.type" alias="app_task"/> | ||
</service> | ||
|
||
.. 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) | ||
; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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('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', | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 | ||
|
@@ -254,40 +331,34 @@ a form that uses the transformer. | |
Because of these, you may choose to :doc:`create a custom field type </cookbook/form/create_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); | ||
} | ||
|
||
public function setDefaultOptions(OptionsResolverInterface $resolver) | ||
{ | ||
$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 | ||
|
||
<service id="acme_demo.type.issue_selector" class="Acme\TaskBundle\Form\Type\IssueSelectorType"> | ||
<argument type="service" id="doctrine.orm.entity_manager"/> | ||
<service id="app.issue_transformer_factory" | ||
class="AppBundle\Form\DataTransformer\IssueToNumberTransformerFactory" public="false"> | ||
<argument type="service" id="doctrine"/> | ||
</service> | ||
|
||
<service id="app.type.issue_selector" | ||
class="AppBundle\Form\IssueSelectorType"> | ||
<argument type="service" id="app.issue_transformer_factory"/> | ||
<tag name="form.type" alias="issue_selector" /> | ||
</service> | ||
|
||
.. 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; | ||
|
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
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.