Skip to content

Commit

Permalink
[Forms] Reworded the article about creating custom form types
Browse files Browse the repository at this point in the history
  • Loading branch information
javiereguiluz committed Jun 28, 2019
1 parent 669fee7 commit ac08120
Show file tree
Hide file tree
Showing 10 changed files with 417 additions and 369 deletions.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions _images/form/form-custom-type-postal-address.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file not shown.
Binary file not shown.
599 changes: 386 additions & 213 deletions form/create_custom_field_type.rst

Large diffs are not rendered by default.

5 changes: 3 additions & 2 deletions form/create_form_type_extension.rst
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,9 @@ For more information on what those methods do, see the
Registering your Form Type Extension as a Service
-------------------------------------------------

Form type extensions must be registered as services and :doc:`tagged </service_container/tags>`
with the ``form.type_extension`` tag. If you're using the
Form type extensions must be :ref:`registered as services <service-container-creating-service>`
and :doc:`tagged </service_container/tags>` with the ``form.type_extension`` tag.
If you're using the
:ref:`default services.yaml configuration <service-container-services-load-example>`,
this is already done for you, thanks to :ref:`autoconfiguration <services-autoconfigure>`.

Expand Down
15 changes: 7 additions & 8 deletions form/data_transformers.rst
Original file line number Diff line number Diff line change
Expand Up @@ -291,14 +291,13 @@ and type-hint the new class::
// ...
}

That's it! As long as you're using :ref:`autowire <services-autowire>` and
:ref:`autoconfigure <services-autoconfigure>`, Symfony will automatically
know to pass your ``TaskType`` an instance of the ``IssueToNumberTransformer``.

.. tip::

For more information about defining form types as services, read
:doc:`register your form type as a service </form/form_dependencies>`.
That's it! If you're using the
:ref:`default services.yaml configuration <service-container-services-load-example>`,
Symfony will automatically know to pass your ``TaskType`` an instance of the
``IssueToNumberTransformer`` thanks to :ref:`autowire <services-autowire>` and
:ref:`autoconfigure <services-autoconfigure>`.
Otherwise, :ref:`register the form class as a service <service-container-creating-service>`
and :doc:`tag it </service_container/tags>` with the ``form.type`` tag.

Now, you can use your ``TaskType``::

Expand Down
9 changes: 5 additions & 4 deletions form/dynamic_form_modification.rst
Original file line number Diff line number Diff line change
Expand Up @@ -326,10 +326,11 @@ security helper to fill in the listener logic::
Using the Form
~~~~~~~~~~~~~~

If you're using :ref:`autowire <services-autowire>` and
:ref:`autoconfigure <services-autoconfigure>`, your form is ready to be used!
Otherwise, see :doc:`/form/form_dependencies` to learn how to register your form
type as a service.
If you're using the :ref:`default services.yaml configuration <service-container-services-load-example>`,
your form is ready to be used thanks to :ref:`autowire <services-autowire>` and
:ref:`autoconfigure <services-autoconfigure>`.
Otherwise, :ref:`register the form class as a service <service-container-creating-service>`
and :doc:`tag it </service_container/tags>` with the ``form.type`` tag.

In a controller, create the form like normal::

Expand Down
150 changes: 9 additions & 141 deletions form/form_dependencies.rst
Original file line number Diff line number Diff line change
@@ -1,144 +1,12 @@
How to Access Services or Config from Inside a Form
===================================================

Sometimes, you may need to access a :doc:`service </service_container>` or other
configuration from inside of your form class. To do this, you have 2 options:

1) Pass Options to your Form
----------------------------

The simplest way to pass services or configuration to your form is via form *options*.
Suppose you need to access the Doctrine entity manager so that you can make a
query. First, allow (in fact, require) a new ``entity_manager`` option to be
passed to your form::

// src/Form/TaskType.php
// ...

class TaskType extends AbstractType
{
// ...

public function configureOptions(OptionsResolver $resolver)
{
// ...

$resolver->setRequired('entity_manager');
}
}

Now that you've done this, you *must* pass an ``entity_manager`` option when you
create your form::

// src/Controller/DefaultController.php
use App\Form\TaskType;

// ...
public function new()
{
$entityManager = $this->getDoctrine()->getManager();

$task = ...;
$form = $this->createForm(TaskType::class, $task, [
'entity_manager' => $entityManager,
]);

// ...
}

Finally, the ``entity_manager`` option is accessible in the ``$options`` argument
of your ``buildForm()`` method::

// src/Form/TaskType.php
// ...

class TaskType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
/** @var \Doctrine\ORM\EntityManager $entityManager */
$entityManager = $options['entity_manager'];
// ...
}

// ...
}

Use this method to pass *anything* to your form.

2) Define your Form as a Service
--------------------------------

Alternatively, you can define your form class as a service. This is a good idea if
you want to re-use the form in several places - registering it as a service makes
this easier.

Suppose you need to access the :ref:`EntityManager <doctrine-entity-manager>` object
so that you can make a query. First, add this as an argument to your form class::

// src/Form/TaskType.php
use Doctrine\ORM\EntityManagerInterface;
// ...

class TaskType extends AbstractType
{
private $entityManager;

public function __construct(EntityManagerInterface $entityManager)
{
$this->entityManager = $entityManager;
}

// ...
}

If you're using :ref:`autowire <services-autowire>` and
:ref:`autoconfigure <services-autoconfigure>`, then you don't need to do *anything*
else: Symfony will automatically know how to pass the correct ``EntityManager`` object
to your ``__construct()`` method.

If you are **not using autowire and autoconfigure**, register your form as a service
manually and tag it with ``form.type``:

.. configuration-block::

.. code-block:: yaml
# config/services.yaml
services:
App\Form\TaskType:
arguments: ['@doctrine.orm.entity_manager']
tags: [form.type]
.. code-block:: xml
<!-- config/services.xml -->
<?xml version="1.0" encoding="UTF-8" ?>
<container xmlns="http://symfony.com/schema/dic/services"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://symfony.com/schema/dic/services
https://symfony.com/schema/dic/services/services-1.0.xsd">
<services>
<service id="App\Form\TaskType">
<argument type="service" id="doctrine.orm.entity_manager"/>
<tag name="form.type"/>
</service>
</services>
</container>
.. code-block:: php
// config/services.php
use App\Form\TaskType;
use Symfony\Component\DependencyInjection\Reference;
$container->register(TaskType::class)
->addArgument(new Reference('doctrine.orm.entity_manager'))
->addTag('form.type')
;
That's it! Your controller - where you create the form - doesn't need to change
at all: Symfony is smart enough to load the ``TaskType`` from the container.

Read :ref:`form-field-service` for more information.
The content of this article is no longer relevant because in current Symfony
versions, form classes are services by default and you can inject services in
them using the :doc:`service autowiring </service_container/autowiring>` feature.

Read the article about :doc:`creating custom form types </form/create_custom_field_type>`
to see an example of how to inject the database service into a form type. In the
same article you can also read about
:ref:`configuration options for form types <form-type-config-options>`, which is
another way of passing services to forms.
6 changes: 5 additions & 1 deletion form/use_empty_data.rst
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,11 @@ The point is, you can set ``empty_data`` to the exact "new" object that you want
.. tip::

In order to pass arguments to the ``BlogType`` constructor, you'll need to
:doc:`register it as a service and tag with form.type </form/form_dependencies>`.
:ref:`register the form as a service <service-container-creating-service>`
and :doc:`tag it </service_container/tags>` with ``form.type``.
If you're using the
:ref:`default services.yaml configuration <service-container-services-load-example>`,
this is already done for you.

.. _forms-empty-data-closure:

Expand Down

0 comments on commit ac08120

Please sign in to comment.