1
1
.. index ::
2
2
single: Events; Create listener
3
+ single: Create subscriber
3
4
4
- How to Create an Event Listener
5
- ===============================
5
+ How to Create Event Listeners and Subscribers
6
+ =============================================
6
7
7
8
Symfony has various events and hooks that can be used to trigger custom
8
9
behavior in your application. Those events are thrown by the HttpKernel
9
10
component and can be viewed in the :class: `Symfony\\ Component\\ HttpKernel\\ KernelEvents ` class.
10
11
11
12
To hook into an event and add your own custom logic, you have to create
12
- a service that will act as an event listener on that event. In this entry,
13
- you will create a service that will act as an exception listener, allowing
14
- you to modify how exceptions are shown by your application. The ``KernelEvents::EXCEPTION ``
15
- event is just one of the core kernel events::
13
+ a service that listens to that event. You can do that in two different ways,
14
+ creating an event listener or an event subscriber instead. In this entry,
15
+ you will see the two ways of creating a service that will act as an exception
16
+ listener, allowing you to modify how exceptions are shown by your application.
17
+ The ``KernelEvents::EXCEPTION `` event is just one of the core kernel events.
16
18
17
- // src/AppBundle/EventListener/AcmeExceptionListener.php
19
+ Creating an Event Listener
20
+ --------------------------
21
+
22
+ The most common way to listen to an event is to register an event listener::
23
+
24
+ // src/AppBundle/EventListener/ExceptionListener.php
18
25
namespace AppBundle\EventListener;
19
26
20
27
use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent;
21
28
use Symfony\Component\HttpFoundation\Response;
22
29
use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface;
23
30
24
- class AcmeExceptionListener
31
+ class ExceptionListener
25
32
{
26
33
public function onKernelException(GetResponseForExceptionEvent $event)
27
34
{
@@ -43,26 +50,23 @@ event is just one of the core kernel events::
43
50
$response->setStatusCode($exception->getStatusCode());
44
51
$response->headers->replace($exception->getHeaders());
45
52
} else {
46
- $response->setStatusCode(500 );
53
+ $response->setStatusCode(Response::HTTP_INTERNAL_SERVER_ERROR );
47
54
}
48
55
49
56
// Send the modified response object to the event
50
57
$event->setResponse($response);
51
58
}
52
59
}
53
60
61
+ .. versionadded :: 2.4
62
+ Support for HTTP status code constants was introduced in Symfony 2.4.
63
+
54
64
.. tip ::
55
65
56
66
Each event receives a slightly different type of ``$event `` object. For
57
67
the ``kernel.exception `` event, it is :class: `Symfony\\ Component\\ HttpKernel\\ Event\\ GetResponseForExceptionEvent `.
58
68
To see what type of object each event listener receives, see :class: `Symfony\\ Component\\ HttpKernel\\ KernelEvents `.
59
69
60
- .. note ::
61
-
62
- When setting a response for the ``kernel.request ``, ``kernel.view `` or
63
- ``kernel.exception `` events, the propagation is stopped, so the lower
64
- priority listeners on that event don't get called.
65
-
66
70
Now that the class is created, you just need to register it as a service and
67
71
notify Symfony that it is a "listener" on the ``kernel.exception `` event by
68
72
using a special "tag":
@@ -71,7 +75,7 @@ using a special "tag":
71
75
72
76
.. code-block :: yaml
73
77
74
- # app/config/services .yml
78
+ # app/config/config .yml
75
79
services :
76
80
kernel.listener.your_listener_name :
77
81
class : AppBundle\EventListener\AcmeExceptionListener
@@ -80,14 +84,14 @@ using a special "tag":
80
84
81
85
.. code-block :: xml
82
86
83
- <!-- app/config/services .xml -->
87
+ <!-- app/config/config .xml -->
84
88
<service id =" kernel.listener.your_listener_name" class =" AppBundle\EventListener\AcmeExceptionListener" >
85
89
<tag name =" kernel.event_listener" event =" kernel.exception" method =" onKernelException" />
86
90
</service >
87
91
88
92
.. code-block :: php
89
93
90
- // app/config/services .php
94
+ // app/config/config .php
91
95
$container
92
96
->register('kernel.listener.your_listener_name', 'AppBundle\EventListener\AcmeExceptionListener')
93
97
->addTag('kernel.event_listener', array('event' => 'kernel.exception', 'method' => 'onKernelException'))
@@ -96,12 +100,124 @@ using a special "tag":
96
100
.. note ::
97
101
98
102
There is an additional tag option ``priority `` that is optional and defaults
99
- to 0. The listeners will be executed in the order of their priority (highest to lowest).
100
- This is useful when you need to guarantee that one listener is executed before another.
103
+ to 0. This value can be from -255 to 255, and the listeners will be executed
104
+ in the order of their priority (highest to lowest). This is useful when
105
+ you need to guarantee that one listener is executed before another.
106
+
107
+ Creating an Event Subscriber
108
+ ----------------------------
109
+
110
+ Another way to listen to events is via an event subscriber. An event subscriber
111
+ can define one or various methods that listen to one or various events,
112
+ and can set a priority for each method. The higher the priority, the earlier
113
+ the method is called. To learn more about event subscribers, see :doc: `/components/event_dispatcher/introduction `.
114
+ The following example shows a subscriber that subscribes various methods
115
+ to the ``kernel.exception `` event::
116
+
117
+ // src/AppBundle/EventListener/ExceptionSubscriber.php
118
+ namespace AppBundle\EventSubscriber;
119
+
120
+ use Symfony\Component\EventDispatcher\EventSubscriberInterface;
121
+ use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent;
122
+ use Symfony\Component\HttpFoundation\Response;
123
+ use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface;
124
+
125
+ class ExceptionSubscriber implements EventSubscriberInterface
126
+ {
127
+ public static function getSubscribedEvents()
128
+ {
129
+ // Return the events it is subscribed to, the methods that listen each event and the
130
+ // priority of each method
131
+ return array(
132
+ 'kernel.exception' => array(
133
+ array('onKernelExceptionPre', 10),
134
+ array('onKernelExceptionMid', 5),
135
+ array('onKernelExceptionPost', 0),
136
+ )
137
+ );
138
+ }
139
+
140
+ public function onKernelExceptionPre(GetResponseForExceptionEvent $event)
141
+ {
142
+ $exception = $event->getException();
143
+ $message = sprintf(
144
+ 'My Error says: %s with code: %s',
145
+ $exception->getMessage(),
146
+ $exception->getCode()
147
+ );
148
+
149
+ $response = new Response();
150
+ $response->setContent($message);
151
+
152
+ if ($exception instanceof HttpExceptionInterface) {
153
+ $response->setStatusCode($exception->getStatusCode());
154
+ $response->headers->replace($exception->getHeaders());
155
+ } else {
156
+ $response->setStatusCode(Response::HTTP_INTERNAL_SERVER_ERROR);
157
+ }
158
+
159
+ $event->setResponse($response);
160
+ }
161
+
162
+ public function onKernerlExceptionMid(GetResponseForExceptionEvent $event)
163
+ {
164
+ // ...
165
+ }
166
+
167
+ public function onKernerlExceptionPost(GetResponseForExceptionEvent $event)
168
+ {
169
+ // ...
170
+ }
171
+ }
172
+
173
+ Now, you just need to register the class as a service and notify Symfony that it
174
+ is an event subscriber:
175
+
176
+ .. configuration-block ::
177
+
178
+ .. code-block :: yaml
179
+
180
+ # app/config/config.yml
181
+ services :
182
+ kernel.listener.your_subscriber_name :
183
+ class : AppBundle\EventSubscriber\AcmeExceptionSubscriber
184
+ tags :
185
+ - { name: kernel.event_subscriber }
186
+
187
+ .. code-block :: xml
188
+
189
+ <!-- app/config/config.xml -->
190
+ <?xml version =" 1.0" encoding =" UTF-8" ?>
191
+ <container xmlns =" http://symfony.com/schema/dic/services" >
192
+
193
+ <services >
194
+ <service id =" acme_exception_subscriber"
195
+ class =" AppBundle\EventSubscriber\AcmeExceptionSubscriber" >
196
+
197
+ <tag name =" kernel.event_subscriber" />
198
+
199
+ </service >
200
+ </services >
201
+ </container >
202
+
203
+ .. code-block :: php
204
+
205
+ // app/config/config.php
206
+ $container
207
+ ->register(
208
+ 'acme_exception_subscriber',
209
+ 'AppBundle\EventSubscriber\AcmeExceptionSubscriber'
210
+ )
211
+ ->addTag('kernel.event_subscriber')
212
+ ;
101
213
102
214
Request Events, Checking Types
103
215
------------------------------
104
216
217
+ .. versionadded :: 2.4
218
+ The ``isMasterRequest() `` method was introduced in Symfony 2.4.
219
+ Prior, the ``getRequestType() `` method must be used.
220
+
105
221
A single page can make several requests (one master request, and then multiple
106
222
sub-requests), which is why when working with the ``KernelEvents::REQUEST ``
107
223
event, you might need to check the type of the request. This can be easily
@@ -117,7 +233,7 @@ done as follow::
117
233
{
118
234
public function onKernelRequest(GetResponseEvent $event)
119
235
{
120
- if (HttpKernel::MASTER_REQUEST != $event->getRequestType ()) {
236
+ if (! $event->isMasterRequest ()) {
121
237
// don't do anything if it's not the master request
122
238
return;
123
239
}
@@ -131,3 +247,5 @@ done as follow::
131
247
Two types of request are available in the :class: `Symfony\\ Component\\ HttpKernel\\ HttpKernelInterface `
132
248
interface: ``HttpKernelInterface::MASTER_REQUEST `` and
133
249
``HttpKernelInterface::SUB_REQUEST ``.
250
+
251
+ .. _`The EventDispatcher component` : http://symfony.com/doc/current/components/event_dispatcher/index.html
0 commit comments