Skip to content

Commit ac9e6b3

Browse files
committed
Moving event_dispatcher/event_listener.rst -> event_dispatcher.rst
1 parent 3918ee8 commit ac9e6b3

File tree

7 files changed

+290
-292
lines changed

7 files changed

+290
-292
lines changed

_build/redirection_map

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@
4444
/cookbook/security/voters_data_permission /cookbook/security/voters
4545
/cookbook/configuration/pdo_session_storage /cookbook/doctrine/pdo_session_storage
4646
/cookbook/configuration/mongodb_session_storage /cookbook/doctrine/mongodb_session_storage
47-
/cookbook/service_container/event_listener /cookbook/event_dispatcher/event_listener
47+
/cookbook/service_container/event_listener /event_dispatcher
4848
/create_framework/http-foundation /create_framework/http_foundation
4949
/create_framework/front-controller /create_framework/front_controller
5050
/create_framework/http-kernel-controller-resolver /create_framework/http_kernel_controller_resolver
@@ -137,7 +137,7 @@
137137
/cookbook/email/testing /email/testing
138138
/cookbook/event_dispatcher/before_after_filters /event_dispatcher/before_after_filters
139139
/cookbook/event_dispatcher/class_extension /event_dispatcher/class_extension
140-
/cookbook/event_dispatcher/event_listener /event_dispatcher/event_listener
140+
/cookbook/event_dispatcher/event_listener /event_dispatcher
141141
/cookbook/event_dispatcher/method_behavior /event_dispatcher/method_behavior
142142
/cookbook/expressions /expressions/expressions
143143
/cookbook/form/create_custom_field_type /form/create_custom_field_type

controller/error_pages.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -344,7 +344,7 @@ before, but also requires a thorough understanding of Symfony internals. Suppose
344344
that your code throws specialized exceptions with a particular meaning to your
345345
application domain.
346346

347-
:doc:`Writing your own event listener </event_dispatcher/event_listener>`
347+
:doc:`Writing your own event listener </event_dispatcher>`
348348
for the ``kernel.exception`` event allows you to have a closer look at the exception
349349
and take different actions depending on it. Those actions might include logging
350350
the exception, redirecting the user to another page or rendering specialized

event_dispatcher.rst

Lines changed: 283 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,286 @@
1-
Event Dispatcher
2-
================
1+
.. index::
2+
single: Events; Create listener
3+
single: Create subscriber
4+
5+
Events and Event Listeners
6+
==========================
7+
8+
During the execution of a Symfony application, lots of event notifications are
9+
triggered. Your application can listen to these notifications and respond to
10+
them by executing any piece of code.
11+
12+
Internal events provided by Symfony itself are defined in the
13+
:class:`Symfony\\Component\\HttpKernel\\KernelEvents` class. Third-party bundles
14+
and libraries also trigger lots of events and your own application can trigger
15+
:doc:`custom events </components/event_dispatcher>`.
16+
17+
All the examples shown in this article use the same ``KernelEvents::EXCEPTION``
18+
event for consistency purposes. In your own application, you can use any event
19+
and even mix several of them in the same subscriber.
20+
21+
Creating an Event Listener
22+
--------------------------
23+
24+
The most common way to listen to an event is to register an **event listener**::
25+
26+
// src/AppBundle/EventListener/ExceptionListener.php
27+
namespace AppBundle\EventListener;
28+
29+
use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent;
30+
use Symfony\Component\HttpFoundation\Response;
31+
use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface;
32+
33+
class ExceptionListener
34+
{
35+
public function onKernelException(GetResponseForExceptionEvent $event)
36+
{
37+
// You get the exception object from the received event
38+
$exception = $event->getException();
39+
$message = sprintf(
40+
'My Error says: %s with code: %s',
41+
$exception->getMessage(),
42+
$exception->getCode()
43+
);
44+
45+
// Customize your response object to display the exception details
46+
$response = new Response();
47+
$response->setContent($message);
48+
49+
// HttpExceptionInterface is a special type of exception that
50+
// holds status code and header details
51+
if ($exception instanceof HttpExceptionInterface) {
52+
$response->setStatusCode($exception->getStatusCode());
53+
$response->headers->replace($exception->getHeaders());
54+
} else {
55+
$response->setStatusCode(Response::HTTP_INTERNAL_SERVER_ERROR);
56+
}
57+
58+
// Send the modified response object to the event
59+
$event->setResponse($response);
60+
}
61+
}
62+
63+
.. tip::
64+
65+
Each event receives a slightly different type of ``$event`` object. For
66+
the ``kernel.exception`` event, it is :class:`Symfony\\Component\\HttpKernel\\Event\\GetResponseForExceptionEvent`.
67+
To see what type of object each event listener receives, see :class:`Symfony\\Component\\HttpKernel\\KernelEvents`
68+
or the documentation about the specific event you're listening to.
69+
70+
Now that the class is created, you just need to register it as a service and
71+
notify Symfony that it is a "listener" on the ``kernel.exception`` event by
72+
using a special "tag":
73+
74+
.. configuration-block::
75+
76+
.. code-block:: yaml
77+
78+
# app/config/services.yml
79+
services:
80+
app.exception_listener:
81+
class: AppBundle\EventListener\ExceptionListener
82+
tags:
83+
- { name: kernel.event_listener, event: kernel.exception }
84+
85+
.. code-block:: xml
86+
87+
<!-- app/config/services.xml -->
88+
<?xml version="1.0" encoding="UTF-8" ?>
89+
<container xmlns="http://symfony.com/schema/dic/services"
90+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
91+
xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">
92+
93+
<services>
94+
<service id="app.exception_listener"
95+
class="AppBundle\EventListener\ExceptionListener">
96+
97+
<tag name="kernel.event_listener" event="kernel.exception" />
98+
</service>
99+
</services>
100+
</container>
101+
102+
.. code-block:: php
103+
104+
// app/config/services.php
105+
$container
106+
->register('app.exception_listener', 'AppBundle\EventListener\ExceptionListener')
107+
->addTag('kernel.event_listener', array('event' => 'kernel.exception'))
108+
;
109+
110+
.. note::
111+
112+
There is an optional tag attribute called ``method`` which defines which method
113+
to execute when the event is triggered. By default the name of the method is
114+
``on`` + "camel-cased event name". If the event is ``kernel.exception`` the
115+
method executed by default is ``onKernelException()``.
116+
117+
The other optional tag attribute is called ``priority``, which defaults to
118+
``0`` and it controls the order in which listeners are executed (the highest
119+
the priority, the earlier a listener is executed). This is useful when you
120+
need to guarantee that one listener is executed before another. The priorities
121+
of the internal Symfony listeners usually range from ``-255`` to ``255`` but
122+
your own listeners can use any positive or negative integer.
123+
124+
Creating an Event Subscriber
125+
----------------------------
126+
127+
Another way to listen to events is via an **event subscriber**, which is a class
128+
that defines one or more methods that listen to one or various events. The main
129+
difference with the event listeners is that subscribers always know which events
130+
they are listening to.
131+
132+
In a given subscriber, different methods can listen to the same event. The order
133+
in which methods are executed is defined by the ``priority`` parameter of each
134+
method (the higher the priority the earlier the method is called). To learn more
135+
about event subscribers, read :doc:`/components/event_dispatcher`.
136+
137+
The following example shows an event subscriber that defines several methods which
138+
listen to the same ``kernel.exception`` event::
139+
140+
// src/AppBundle/EventSubscriber/ExceptionSubscriber.php
141+
namespace AppBundle\EventSubscriber;
142+
143+
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
144+
use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent;
145+
use Symfony\Component\HttpKernel\KernelEvents;
146+
147+
class ExceptionSubscriber implements EventSubscriberInterface
148+
{
149+
public static function getSubscribedEvents()
150+
{
151+
// return the subscribed events, their methods and priorities
152+
return array(
153+
KernelEvents::EXCEPTION => array(
154+
array('processException', 10),
155+
array('logException', 0),
156+
array('notifyException', -10),
157+
)
158+
);
159+
}
160+
161+
public function processException(GetResponseForExceptionEvent $event)
162+
{
163+
// ...
164+
}
165+
166+
public function logException(GetResponseForExceptionEvent $event)
167+
{
168+
// ...
169+
}
170+
171+
public function notifyException(GetResponseForExceptionEvent $event)
172+
{
173+
// ...
174+
}
175+
}
176+
177+
Now, you just need to register the class as a service and add the
178+
``kernel.event_subscriber`` tag to tell Symfony that this is an event subscriber:
179+
180+
.. configuration-block::
181+
182+
.. code-block:: yaml
183+
184+
# app/config/services.yml
185+
services:
186+
app.exception_subscriber:
187+
class: AppBundle\EventSubscriber\ExceptionSubscriber
188+
tags:
189+
- { name: kernel.event_subscriber }
190+
191+
.. code-block:: xml
192+
193+
<!-- app/config/services.xml -->
194+
<?xml version="1.0" encoding="UTF-8" ?>
195+
<container xmlns="http://symfony.com/schema/dic/services"
196+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
197+
xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">
198+
199+
<services>
200+
<service id="app.exception_subscriber"
201+
class="AppBundle\EventSubscriber\ExceptionSubscriber">
202+
203+
<tag name="kernel.event_subscriber"/>
204+
</service>
205+
</services>
206+
</container>
207+
208+
.. code-block:: php
209+
210+
// app/config/services.php
211+
$container
212+
->register(
213+
'app.exception_subscriber',
214+
'AppBundle\EventSubscriber\ExceptionSubscriber'
215+
)
216+
->addTag('kernel.event_subscriber')
217+
;
218+
219+
Request Events, Checking Types
220+
------------------------------
221+
222+
A single page can make several requests (one master request, and then multiple
223+
sub-requests - typically by :doc:`/templating/embedding_controllers`). For the core
224+
Symfony events, you might need to check to see if the event is for a "master" request
225+
or a "sub request"::
226+
227+
// src/AppBundle/EventListener/RequestListener.php
228+
namespace AppBundle\EventListener;
229+
230+
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
231+
use Symfony\Component\HttpKernel\HttpKernel;
232+
use Symfony\Component\HttpKernel\HttpKernelInterface;
233+
234+
class RequestListener
235+
{
236+
public function onKernelRequest(GetResponseEvent $event)
237+
{
238+
if (!$event->isMasterRequest()) {
239+
// don't do anything if it's not the master request
240+
return;
241+
}
242+
243+
// ...
244+
}
245+
}
246+
247+
Certain things, like checking information on the *real* request, may not need to
248+
be done on the sub-request listeners.
249+
250+
.. _events-or-subscribers:
251+
252+
Listeners or Subscribers
253+
------------------------
254+
255+
Listeners and subscribers can be used in the same application indistinctly. The
256+
decision to use either of them is usually a matter of personal taste. However,
257+
there are some minor advantages for each of them:
258+
259+
* **Subscribers are easier to reuse** because the knowledge of the events is kept
260+
in the class rather than in the service definition. This is the reason why
261+
Symfony uses subscribers internally;
262+
* **Listeners are more flexible** because bundles can enable or disable each of
263+
them conditionally depending on some configuration value.
264+
265+
Debugging Event Listeners
266+
-------------------------
267+
268+
.. versionadded:: 2.6
269+
The ``debug:event-dispatcher`` command was introduced in Symfony 2.6.
270+
271+
You can find out what listeners are registered in the event dispatcher
272+
using the console. To show all events and their listeners, run:
273+
274+
.. code-block:: bash
275+
276+
$ php app/console debug:event-dispatcher
277+
278+
You can get registered listeners for a particular event by specifying
279+
its name:
280+
281+
.. code-block:: bash
282+
283+
$ php app/console debug:event-dispatcher kernel.exception
3284
4285
.. toctree::
5286
:maxdepth: 1

event_dispatcher/before_after_filters.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ Creating an Event Listener
102102

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

107107
// src/AppBundle/EventListener/TokenListener.php
108108
namespace AppBundle\EventListener;

0 commit comments

Comments
 (0)