Skip to content

More "id" => type hints / autowiring changes #7883

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 1 commit into from
May 10, 2017
Merged
Show file tree
Hide file tree
Changes from all 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
37 changes: 20 additions & 17 deletions controller/argument_value_resolver.rst
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ Functionality Shipped with the HttpKernel
-----------------------------------------

.. versionadded:: 3.3
The ``SessionValueResolver`` was introduced in Symfony 3.3.
The ``SessionValueResolver`` and ``ServiceValueResolver`` were both added in Symfony 3.3.

Symfony ships with five value resolvers in the HttpKernel component:

Expand All @@ -27,6 +27,10 @@ Symfony ships with five value resolvers in the HttpKernel component:
Injects the current ``Request`` if type-hinted with ``Request`` or a class
extending ``Request``.

:class:`Symfony\\Component\\HttpKernel\\Controller\\ArgumentResolver\\ServiceValueResolver`
Injects a service if type-hinted with a valid service class or interface. This
works like :doc:`autowiring </service_container/autowiring>`.

:class:`Symfony\\Component\\HttpKernel\\Controller\\ArgumentResolver\\SessionValueResolver`
Injects the configured session class extending ``SessionInterface`` if
type-hinted with ``SessionInterface`` or a class extending
Expand Down Expand Up @@ -146,10 +150,12 @@ and adding a priority.

# app/config/services.yml
services:
app.value_resolver.user:
class: AppBundle\ArgumentResolver\UserValueResolver
arguments:
- '@security.token_storage'
_defaults:
# ... be sure autowiring is enabled
autowire: true
# ...

AppBundle\ArgumentResolver\UserValueResolver:
tags:
- { name: controller.argument_value_resolver, priority: 50 }

Expand All @@ -162,10 +168,11 @@ and adding a priority.
xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">

<services>
<service id="app.value_resolver.user"
class="AppBundle\ArgumentResolver\UserValueResolver"
>
<argument type="service" id="security.token_storage">
<!-- ... be sure autowiring is enabled -->
<defaults autowire="true" ... />
<!-- ... -->

<service id="AppBundle\ArgumentResolver\UserValueResolver">
<tag name="controller.argument_value_resolver" priority="50" />
</service>
</services>
Expand All @@ -175,14 +182,10 @@ and adding a priority.
.. code-block:: php

// app/config/services.php
use Symfony\Component\DependencyInjection\Definition;

$definition = new Definition(
'AppBundle\ArgumentResolver\UserValueResolver',
array(new Reference('security.token_storage'))
);
$definition->addTag('controller.argument_value_resolver', array('priority' => 50));
$container->setDefinition('app.value_resolver.user', $definition);
use AppBundle\ArgumentResolver\UserValueResolver;

$container->autowire(UserValueResolver::class)
->addTag('controller.argument_value_resolver', array('priority' => 50));

While adding a priority is optional, it's recommended to add one to make sure
the expected value is injected. The ``RequestAttributeValueResolver`` has a
Expand Down
34 changes: 17 additions & 17 deletions controller/error_pages.rst
Original file line number Diff line number Diff line change
Expand Up @@ -269,9 +269,15 @@ In that case, you might want to override one or both of the ``showAction()`` and

# app/config/services.yml
services:
app.exception_controller:
class: AppBundle\Controller\CustomExceptionController
arguments: ['@twig', '%kernel.debug%']
_defaults:
# ... be sure autowiring is enabled
autowire: true
# ...

AppBundle\Controller\CustomExceptionController:
public: true
arguments:
$debug: '%kernel.debug%'

.. code-block:: xml

Expand All @@ -282,11 +288,12 @@ In that case, you might want to override one or both of the ``showAction()`` and
xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd"
>
<services>
<service id="app.exception_controller"
class="AppBundle\Controller\CustomExceptionController"
>
<argument type="service" id="twig"/>
<argument>%kernel.debug%</argument>
<!-- ... be sure autowiring is enabled -->
<defaults autowire="true" ... />
<!-- ... -->

<service id="AppBundle\Controller\CustomExceptionController" public="true">
<argument key="$debug">%kernel.debug%</argument>
</service>
</services>
</container>
Expand All @@ -295,16 +302,9 @@ In that case, you might want to override one or both of the ``showAction()`` and

// app/config/services.php
use AppBundle\Controller\CustomExceptionController;
use Symfony\Component\DependencyInjection\Reference;

$container->register('app.exception_controller', CustomExceptionController::class)
->setArguments(array(
new Reference('twig'),
'%kernel.debug%',
));

And then configure ``twig.exception_controller`` using the controller as
services syntax (e.g. ``app.exception_controller:showAction``).
$container->autowire(CustomExceptionController::class)
->setArgument('$debug', '%kernel.debug%');

.. tip::

Expand Down
66 changes: 41 additions & 25 deletions controller/soap_web_service.rst
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ which represents the functionality that you'll expose in your SOAP service.
In this case, the SOAP service will allow the client to call a method called
``hello``, which happens to send an email::

// src/Acme/SoapBundle/Services/HelloService.php
namespace Acme\SoapBundle\Services;
// src/AppBundle/Service/HelloService.php
namespace AppBundle\Service;

class HelloService
{
Expand All @@ -50,56 +50,72 @@ In this case, the SOAP service will allow the client to call a method called
}
}

Next, you can train Symfony to be able to create an instance of this class.
Since the class sends an email, it's been designed to accept a ``Swift_Mailer``
instance. Using the Service Container, you can configure Symfony to construct
a ``HelloService`` object properly:
Next, make sure that your new class is registered as a service. If you use
:doc:`autowiring </service_container/autowiring>` (enabled by default in the Symfony
Standard Edition), this is easy:

.. configuration-block::

.. code-block:: yaml

# app/config/services.yml
services:
hello_service:
class: Acme\SoapBundle\Services\HelloService
arguments: ['@mailer']
_defaults:
# ... be sure autowiring is enabled
autowire: true
# ...

# add Service/ to the list of directories to load services from
AppBundle\:
resource: '../../src/AppBundle/{Service,Updates,Command,Form,EventSubscriber,Twig,Security}'

.. code-block:: xml

<!-- app/config/services.xml -->
<services>
<service id="hello_service" class="Acme\SoapBundle\Services\HelloService">
<argument type="service" id="mailer"/>
</service>
</services>
<?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
http://symfony.com/schema/dic/services/services-1.0.xsd">

<services>
<!-- ... be sure autowiring is enabled -->
<defaults autowire="true" ... />
<!-- ... -->

<!-- add Service/ to the list of directories to load services from -->
<prototype namespace="AppBundle\" resource="../../src/AppBundle/{Service,Updates,Command,Form,EventSubscriber,Twig,Security}" />
</services>
</container>

.. code-block:: php

// app/config/services.php
use Acme\SoapBundle\Services\HelloService;
use AppBundle\Service\HelloService;

$container
->register('hello_service', HelloService::class)
->addArgument(new Reference('mailer'));
$container->autowire(HelloService::class)
->setPublic(false);

Below is an example of a controller that is capable of handling a SOAP
request. If ``indexAction()`` is accessible via the route ``/soap``, then the
WSDL document can be retrieved via ``/soap?wsdl``.

.. code-block:: php
request. Because ``indexAction()`` is accessible via ``/soap``, the WSDL document
can be retrieved via ``/soap?wsdl``::

namespace Acme\SoapBundle\Controller;
namespace AppBundle\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Response;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use AppBundle\Service\HelloService;
Copy link
Contributor

Choose a reason for hiding this comment

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

Shouldn't use statements be ordered ?

Copy link
Member Author

Choose a reason for hiding this comment

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

I actually don't know, I didn't see anything (looked quickly) in the docs contributor page, but I could be wrong

Copy link
Contributor

Choose a reason for hiding this comment

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

Me neither but I often see them ordered in symfony's code.

Copy link
Member Author

Choose a reason for hiding this comment

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

Ah, they do follow that standard in core. I suppose we could do, but I'll worry about that later ;)


class HelloServiceController extends Controller
{
public function indexAction()
/**
* @Route("/soap")
*/
public function indexAction(HelloService $helloService)
{
$server = new \SoapServer('/path/to/hello.wsdl');
$server->setObject($this->get('hello_service'));
$server->setObject($helloService);

$response = new Response();
$response->headers->set('Content-Type', 'text/xml; charset=ISO-8859-1');
Expand Down
81 changes: 49 additions & 32 deletions controller/upload_file.rst
Original file line number Diff line number Diff line change
Expand Up @@ -221,8 +221,8 @@ Creating an Uploader Service
To avoid logic in controllers, making them big, you can extract the upload
logic to a separate service::

// src/AppBundle/FileUploader.php
namespace AppBundle;
// src/AppBundle/Service/FileUploader.php
namespace AppBundle\Service;

use Symfony\Component\HttpFoundation\File\UploadedFile;

Expand Down Expand Up @@ -259,47 +259,51 @@ Then, define a service for this class:
# app/config/services.yml
services:
# ...
app.brochure_uploader:
class: AppBundle\FileUploader
arguments: ['%brochures_directory%']

AppBundle\Service\FileUploader:
arguments:
$targetDir: '%brochures_directory%'

.. code-block:: xml

<!-- app/config/config.xml -->
<!-- app/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
http://symfony.com/schema/dic/services/services-1.0.xsd"
>
<!-- ... -->
http://symfony.com/schema/dic/services/services-1.0.xsd">

<service id="app.brochure_uploader" class="AppBundle\FileUploader">
<argument>%brochures_directory%</argument>
</service>
<services>
<!-- ... -->

<service id="AppBundle\Service\FileUploader">
<argument key="$targetDir">%brochures_directory%</argument>
</service>
</services>
</container>

.. code-block:: php

// app/config/services.php
use AppBundle\FileUploader;
use AppBundle\Service\FileUploader;

// ...
$container->register('app.brochure_uploader', FileUploader::class)
->addArgument('%brochures_directory%');
$container->autowire(FileUploader::class)
->setArgument('$targetDir', '%brochures_directory%');

Now you're ready to use this service in the controller::

// src/AppBundle/Controller/ProductController.php
use Symfony\Component\HttpFoundation\Request;
use AppBundle\Service\FileUploader;

// ...
public function newAction(Request $request)
public function newAction(Request $request, FileUploader $fileUploader)
Copy link
Contributor

Choose a reason for hiding this comment

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

What about adding a use statement for Request too?

{
// ...

if ($form->isSubmitted() && $form->isValid()) {
$file = $product->getBrochure();
$fileName = $this->get('app.brochure_uploader')->upload($file);
$fileName = $fileUploader->upload($file);

$product->setBrochure($fileName);

Expand All @@ -323,7 +327,7 @@ automatically upload the file when persisting the entity::
use Doctrine\ORM\Event\LifecycleEventArgs;
use Doctrine\ORM\Event\PreUpdateEventArgs;
use AppBundle\Entity\Product;
use AppBundle\FileUploader;
use AppBundle\Service\FileUploader;

class BrochureUploadListener
{
Expand Down Expand Up @@ -375,10 +379,12 @@ Now, register this class as a Doctrine listener:

# app/config/services.yml
services:
_defaults:
# ... be sure autowiring is enabled
autowire: true
# ...
app.doctrine_brochure_listener:
class: AppBundle\EventListener\BrochureUploadListener
arguments: ['@app.brochure_uploader']

AppBundle\EventListener\BrochureUploadListener:
tags:
- { name: doctrine.event_listener, event: prePersist }
- { name: doctrine.event_listener, event: preUpdate }
Expand All @@ -392,33 +398,44 @@ Now, register this class as a Doctrine listener:
xsi:schemaLocation="http://symfony.com/schema/dic/services
http://symfony.com/schema/dic/services/services-1.0.xsd"
>
<!-- ... -->

<service id="app.doctrine_brochure_listener"
class="AppBundle\EventListener\BrochureUploaderListener"
>
<argument type="service" id="app.brochure_uploader"/>

<tag name="doctrine.event_listener" event="prePersist"/>
<tag name="doctrine.event_listener" event="preUpdate"/>
</service>
<services>
<!-- ... be sure autowiring is enabled -->
<defaults autowire="true" ... />
<!-- ... -->

<service id="AppBundle\EventListener\BrochureUploaderListener">
<tag name="doctrine.event_listener" event="prePersist"/>
<tag name="doctrine.event_listener" event="preUpdate"/>
</service>
</services>
</container>

.. code-block:: php

// app/config/services.php
use AppBundle\EventListener\BrochureUploaderListener;
<<<<<<< HEAD
use Symfony\Component\DependencyInjection\Reference;

// ...
$container->register('app.doctrine_brochure_listener', BrochureUploaderListener::class)
->addArgument(new Reference('brochures_directory'))
=======

$container->autowire(BrochureUploaderListener::class)
>>>>>>> 8974c4842... Going through more chapters to use types and autowiring
->addTag('doctrine.event_listener', array(
'event' => 'prePersist',
))
->addTag('doctrine.event_listener', array(
<<<<<<< HEAD
'event' => 'prePersist',
));
=======
'event' => 'preUpdate',
))
;
>>>>>>> 8974c4842... Going through more chapters to use types and autowiring

This listener is now automatically executed when persisting a new Product
entity. This way, you can remove everything related to uploading from the
Expand Down
Loading