Skip to content

Commit e437d9d

Browse files
committed
feature #7906 More updates for "Type-based" injection (weaverryan)
This PR was squashed before being merged into the master branch (closes #7906). Discussion ---------- More updates for "Type-based" injection Apologies for another big PR, and also if I'm stepping on anyone else's feed - I'm just trying to charge through and make all the changes to the docs. This contains 2 things: 1) More updates to entries to favor type-based injection (type-hinting and relying on autowiring) over manually configuration. I have more chapters to do still, but I'm mostly done. 2) Important updates (mostly to `service_container.rst`) now that we're importing *all* of `src/AppBundle` in `services.yml` (symfony/symfony-standard#1070). Side note: wooohooo!!! P.S. I deleted one entry that I thought was really poor and unnecessary. Commits ------- f0361fa More updates for "Type-based" injection
2 parents 4130883 + f0361fa commit e437d9d

25 files changed

+784
-1114
lines changed

_build/redirection_map

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -334,3 +334,4 @@
334334
/form /forms
335335
/testing/simulating_authentication /testing/http_authentication
336336
/components/dependency_injection/autowiring /service_container/autowiring
337+
/event_dispatcher/class_extension /event_dispatcher

controller.rst

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -288,7 +288,7 @@ controller's service config:
288288
AppBundle\Controller\LuckyController:
289289
public: true
290290
tags:
291-
# add multiple tags to controller multiple args
291+
# add multiple tags to control multiple args
292292
- name: controller.service_arguments
293293
action: numberAction
294294
argument: logger
@@ -338,13 +338,18 @@ in your controllers.
338338

339339
For more information about services, see the :doc:`/service_container` article.
340340

341+
.. _controller-service-arguments-tag:
342+
341343
.. note::
342344
If this isn't working, make sure your controller is registered as a service,
343345
is :ref:`autoconfigured <services-autoconfigure>` and extends either
344346
:class:`Symfony\\Bundle\\FrameworkBundle\\Controller\\Controller` or
345-
:class:`Symfony\\Bundle\\FrameworkBundle\\Controller\\AbstractController`. Or,
346-
you can tag your service manually with ``controller.service_arguments``. All
347-
of this is done for you in a fresh Symfony install.
347+
:class:`Symfony\\Bundle\\FrameworkBundle\\Controller\\AbstractController`. If
348+
you use the :ref:`services.yml configuration from the Symfony Standard Edition <service-container-services-load-example>`,
349+
then your controllers are already registered as services and autoconfigured.
350+
351+
If you're not using the default configuration, you can tag your service manually
352+
with ``controller.service_arguments``.
348353

349354
.. _accessing-other-services:
350355
.. _controller-access-services-directly:

controller/soap_web_service.rst

Lines changed: 4 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -50,53 +50,11 @@ In this case, the SOAP service will allow the client to call a method called
5050
}
5151
}
5252

53-
Next, make sure that your new class is registered as a service. If you use
54-
:doc:`autowiring </service_container/autowiring>` (enabled by default in the Symfony
55-
Standard Edition), this is easy:
53+
Next, make sure that your new class is registered as a service. If you're using
54+
the :ref:`default services configuration <service-container-services-load-example>`,
55+
you don't need to do anything!
5656

57-
.. configuration-block::
58-
59-
.. code-block:: yaml
60-
61-
# app/config/services.yml
62-
services:
63-
_defaults:
64-
# ... be sure autowiring is enabled
65-
autowire: true
66-
# ...
67-
68-
# add Service/ to the list of directories to load services from
69-
AppBundle\:
70-
resource: '../../src/AppBundle/{Service,Updates,Command,Form,EventSubscriber,Twig,Security}'
71-
72-
.. code-block:: xml
73-
74-
<!-- app/config/services.xml -->
75-
<?xml version="1.0" encoding="UTF-8" ?>
76-
<container xmlns="http://symfony.com/schema/dic/services"
77-
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
78-
xsi:schemaLocation="http://symfony.com/schema/dic/services
79-
http://symfony.com/schema/dic/services/services-1.0.xsd">
80-
81-
<services>
82-
<!-- ... be sure autowiring is enabled -->
83-
<defaults autowire="true" ... />
84-
<!-- ... -->
85-
86-
<!-- add Service/ to the list of directories to load services from -->
87-
<prototype namespace="AppBundle\" resource="../../src/AppBundle/{Service,Updates,Command,Form,EventSubscriber,Twig,Security}" />
88-
</services>
89-
</container>
90-
91-
.. code-block:: php
92-
93-
// app/config/services.php
94-
use AppBundle\Service\HelloService;
95-
96-
$container->autowire(HelloService::class)
97-
->setPublic(false);
98-
99-
Below is an example of a controller that is capable of handling a SOAP
57+
Finally, below is an example of a controller that is capable of handling a SOAP
10058
request. Because ``indexAction()`` is accessible via ``/soap``, the WSDL document
10159
can be retrieved via ``/soap?wsdl``::
10260

doctrine.rst

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -551,7 +551,6 @@ a controller, this is pretty easy. Add the following method to the
551551
use Doctrine\ORM\EntityManagerInterface;
552552
use Doctrine\Common\Persistence\ManagerRegistry;
553553

554-
// ...
555554
public function createAction(EntityManagerInterface $em)
556555
{
557556
// or fetch the em via the container
@@ -585,17 +584,19 @@ a controller, this is pretty easy. Add the following method to the
585584

586585
Take a look at the previous example in more detail:
587586

588-
* **lines 10-13** In this section, you instantiate and work with the ``$product``
589-
object like any other normal PHP object.
587+
.. _doctrine-entity-manager:
590588

591-
* **line 15** This line fetches Doctrine's *entity manager* object, which is
592-
responsible for the process of persisting objects to, and fetching objects
593-
from, the database.
589+
* **line 10** The ``EntityManagerInterface`` type-hint tells Symfony to pass you Doctrine's
590+
*entity manager* object, which is the most important object in Doctrine. It's
591+
responsible for saving objects to, and fetching objects from, the database.
592+
593+
* **lines 15-18** In this section, you instantiate and work with the ``$product``
594+
object like any other normal PHP object.
594595

595-
* **line 18** The ``persist($product)`` call tells Doctrine to "manage" the
596+
* **line 21** The ``persist($product)`` call tells Doctrine to "manage" the
596597
``$product`` object. This does **not** cause a query to be made to the database.
597598

598-
* **line 21** When the ``flush()`` method is called, Doctrine looks through
599+
* **line 24** When the ``flush()`` method is called, Doctrine looks through
599600
all of the objects that it's managing to see if they need to be persisted
600601
to the database. In this example, the ``$product`` object's data doesn't
601602
exist in the database, so the entity manager executes an ``INSERT`` query,

event_dispatcher.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,8 @@ listen to the same ``kernel.exception`` event::
179179
That's it! Your ``services.yml`` file should already be setup to load services from
180180
the ``EventSubscriber`` directory. Symfony takes care of the rest.
181181

182+
.. _ref-event-subscriber-configuration:
183+
182184
.. tip::
183185

184186
If your methods are *not* called when an exception is thrown, double-check that

event_dispatcher/before_after_filters.rst

Lines changed: 43 additions & 98 deletions
Original file line numberDiff line numberDiff line change
@@ -67,9 +67,9 @@ parameters key:
6767
Tag Controllers to Be Checked
6868
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
6969

70-
A ``kernel.controller`` listener gets notified on *every* request, right before
71-
the controller is executed. So, first, you need some way to identify if the
72-
controller that matches the request needs token validation.
70+
A ``kernel.controller`` (aka ``KernelEvents::CONTROLLER``) listener gets notified
71+
on *every* request, right before the controller is executed. So, first, you need
72+
some way to identify if the controller that matches the request needs token validation.
7373

7474
A clean and easy way is to create an empty interface and make the controllers
7575
implement it::
@@ -97,21 +97,23 @@ A controller that implements this interface simply looks like this::
9797
}
9898
}
9999

100-
Creating an Event Listener
101-
~~~~~~~~~~~~~~~~~~~~~~~~~~
100+
Creating an Event Subscriber
101+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
102102

103103
Next, you'll need to create an event listener, which will hold the logic
104104
that you want to be executed before your controllers. If you're not familiar with
105105
event listeners, you can learn more about them at :doc:`/event_dispatcher`::
106106

107-
// src/AppBundle/EventListener/TokenListener.php
108-
namespace AppBundle\EventListener;
107+
// src/AppBundle/EventSubscriber/TokenSubscriber.php
108+
namespace AppBundle\EventSubscriber;
109109

110110
use AppBundle\Controller\TokenAuthenticatedController;
111111
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
112112
use Symfony\Component\HttpKernel\Event\FilterControllerEvent;
113+
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
114+
use Symfony\Component\HttpKernel\KernelEvents;
113115

114-
class TokenListener
116+
class TokenSubscriber implements EventSubscriberInterface
115117
{
116118
private $tokens;
117119

@@ -140,52 +142,28 @@ event listeners, you can learn more about them at :doc:`/event_dispatcher`::
140142
}
141143
}
142144
}
143-
}
144-
145-
Registering the Listener
146-
~~~~~~~~~~~~~~~~~~~~~~~~
147-
148-
Finally, register your listener as a service and tag it as an event listener.
149-
By listening on ``kernel.controller``, you're telling Symfony that you want
150-
your listener to be called just before any controller is executed.
151-
152-
.. configuration-block::
153-
154-
.. code-block:: yaml
155145

156-
# app/config/services.yml
157-
services:
158-
app.tokens.action_listener:
159-
class: AppBundle\EventListener\TokenListener
160-
arguments: ['%tokens%']
161-
tags:
162-
- { name: kernel.event_listener, event: kernel.controller, method: onKernelController }
163-
164-
.. code-block:: xml
165-
166-
<!-- app/config/services.xml -->
167-
<service id="app.tokens.action_listener" class="AppBundle\EventListener\TokenListener">
168-
<argument>%tokens%</argument>
169-
<tag name="kernel.event_listener" event="kernel.controller" method="onKernelController" />
170-
</service>
171-
172-
.. code-block:: php
146+
public static function getSubscribedEvents()
147+
{
148+
return array(
149+
KernelEvents::CONTROLLER => 'onKernelController',
150+
);
151+
}
152+
}
173153

174-
// app/config/services.php
175-
use AppBundle\EventListener\TokenListener;
154+
That's it! Your ``services.yml`` file should already be setup to load services from
155+
the ``EventSubscriber`` directory. Symfony takes care of the rest. Your
156+
``TokenSubscriber`` ``onKernelController()`` method will be executed on each request.
157+
If the controller that is about to be executed implements ``TokenAuthenticatedController``,
158+
token authentication is applied. This lets you have a "before" filter on any controller
159+
you want.
176160

177-
$container->register('app.tokens.action_listener', TokenListener::class)
178-
->addArgument('%tokens%')
179-
->addTag('kernel.event_listener', array(
180-
'event' => 'kernel.controller',
181-
'method' => 'onKernelController',
182-
));
161+
.. tip::
183162

184-
With this configuration, your ``TokenListener`` ``onKernelController()`` method
185-
will be executed on each request. If the controller that is about to be executed
186-
implements ``TokenAuthenticatedController``, token authentication is
187-
applied. This lets you have a "before" filter on any controller that you
188-
want.
163+
If your subscriber is *not* called on each request, double-check that
164+
you're :ref:`loading services <service-container-services-load-example>` from
165+
the ``EventSubscriber`` directory and have :ref:`autoconfigure <services-autoconfigure>`
166+
enabled. You can also manually add the ``kernel.event_subscriber`` tag.
189167

190168
After Filters with the ``kernel.response`` Event
191169
------------------------------------------------
@@ -195,12 +173,12 @@ can also add a hook that's executed *after* your controller. For this example,
195173
imagine that you want to add a sha1 hash (with a salt using that token) to
196174
all responses that have passed this token authentication.
197175

198-
Another core Symfony event - called ``kernel.response`` - is notified on
199-
every request, but after the controller returns a Response object. Creating
200-
an "after" listener is as easy as creating a listener class and registering
176+
Another core Symfony event - called ``kernel.response`` (aka ``KernelEvents::RESPONSE``) -
177+
is notified on every request, but after the controller returns a Response object.
178+
Creating an "after" listener is as easy as creating a listener class and registering
201179
it as a service on this event.
202180

203-
For example, take the ``TokenListener`` from the previous example and first
181+
For example, take the ``TokenSubscriber`` from the previous example and first
204182
record the authentication token inside the request attributes. This will
205183
serve as a basic flag that this request underwent token authentication::
206184

@@ -219,9 +197,9 @@ serve as a basic flag that this request underwent token authentication::
219197
}
220198
}
221199

222-
Now, add another method to this class - ``onKernelResponse()`` - that looks
223-
for this flag on the request object and sets a custom header on the response
224-
if it's found::
200+
Now, configure the subscriber to listen to another event and add ``onKernelResponse()``.
201+
This will look for the ``auth_token`` flag on the request object and set a custom
202+
header on the response if it's found::
225203

226204
// add the new use statement at the top of your file
227205
use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
@@ -240,49 +218,16 @@ if it's found::
240218
$response->headers->set('X-CONTENT-HASH', $hash);
241219
}
242220

243-
Finally, a second "tag" is needed in the service definition to notify Symfony
244-
that the ``onKernelResponse`` event should be notified for the ``kernel.response``
245-
event:
246-
247-
.. configuration-block::
248-
249-
.. code-block:: yaml
250-
251-
# app/config/services.yml
252-
services:
253-
app.tokens.action_listener:
254-
class: AppBundle\EventListener\TokenListener
255-
arguments: ['%tokens%']
256-
tags:
257-
- { name: kernel.event_listener, event: kernel.controller, method: onKernelController }
258-
- { name: kernel.event_listener, event: kernel.response, method: onKernelResponse }
259-
260-
.. code-block:: xml
261-
262-
<!-- app/config/services.xml -->
263-
<service id="app.tokens.action_listener" class="AppBundle\EventListener\TokenListener">
264-
<argument>%tokens%</argument>
265-
<tag name="kernel.event_listener" event="kernel.controller" method="onKernelController" />
266-
<tag name="kernel.event_listener" event="kernel.response" method="onKernelResponse" />
267-
</service>
221+
public static function getSubscribedEvents()
222+
{
223+
return array(
224+
KernelEvents::CONTROLLER => 'onKernelController',
225+
KernelEvents::RESPONSE => 'onKernelResponse',
226+
);
227+
}
268228

269-
.. code-block:: php
270229

271-
// app/config/services.php
272-
use AppBundle\EventListener\TokenListener;
273-
274-
$container->register('app.tokens.action_listener', TokenListener::class)
275-
->addArgument('%tokens%')
276-
->addTag('kernel.event_listener', array(
277-
'event' => 'kernel.controller',
278-
'method' => 'onKernelController',
279-
))
280-
->addTag('kernel.event_listener', array(
281-
'event' => 'kernel.response',
282-
'method' => 'onKernelResponse',
283-
));
284-
285-
That's it! The ``TokenListener`` is now notified before every controller is
230+
That's it! The ``TokenSubscriber`` is now notified before every controller is
286231
executed (``onKernelController()``) and after every controller returns a response
287232
(``onKernelResponse()``). By making specific controllers implement the ``TokenAuthenticatedController``
288233
interface, your listener knows which controllers it should take action on.

0 commit comments

Comments
 (0)