From ac9e6b3840fbe37e3acf634d0f6f1e69711a191e Mon Sep 17 00:00:00 2001 From: Ryan Weaver Date: Thu, 14 Jul 2016 15:59:54 -0400 Subject: [PATCH] Moving event_dispatcher/event_listener.rst -> event_dispatcher.rst --- _build/redirection_map | 4 +- controller/error_pages.rst | 2 +- event_dispatcher.rst | 285 +++++++++++++++++++++- event_dispatcher/before_after_filters.rst | 2 +- event_dispatcher/event_listener.rst | 283 --------------------- reference/dic_tags.rst | 4 +- session/locale_sticky_session.rst | 2 +- 7 files changed, 290 insertions(+), 292 deletions(-) delete mode 100644 event_dispatcher/event_listener.rst diff --git a/_build/redirection_map b/_build/redirection_map index 8c1bb17df16..369c6857850 100644 --- a/_build/redirection_map +++ b/_build/redirection_map @@ -44,7 +44,7 @@ /cookbook/security/voters_data_permission /cookbook/security/voters /cookbook/configuration/pdo_session_storage /cookbook/doctrine/pdo_session_storage /cookbook/configuration/mongodb_session_storage /cookbook/doctrine/mongodb_session_storage -/cookbook/service_container/event_listener /cookbook/event_dispatcher/event_listener +/cookbook/service_container/event_listener /event_dispatcher /create_framework/http-foundation /create_framework/http_foundation /create_framework/front-controller /create_framework/front_controller /create_framework/http-kernel-controller-resolver /create_framework/http_kernel_controller_resolver @@ -137,7 +137,7 @@ /cookbook/email/testing /email/testing /cookbook/event_dispatcher/before_after_filters /event_dispatcher/before_after_filters /cookbook/event_dispatcher/class_extension /event_dispatcher/class_extension -/cookbook/event_dispatcher/event_listener /event_dispatcher/event_listener +/cookbook/event_dispatcher/event_listener /event_dispatcher /cookbook/event_dispatcher/method_behavior /event_dispatcher/method_behavior /cookbook/expressions /expressions/expressions /cookbook/form/create_custom_field_type /form/create_custom_field_type diff --git a/controller/error_pages.rst b/controller/error_pages.rst index 62b79117350..3c39eb340f3 100644 --- a/controller/error_pages.rst +++ b/controller/error_pages.rst @@ -344,7 +344,7 @@ before, but also requires a thorough understanding of Symfony internals. Suppose that your code throws specialized exceptions with a particular meaning to your application domain. -:doc:`Writing your own event listener ` +:doc:`Writing your own event listener ` for the ``kernel.exception`` event allows you to have a closer look at the exception and take different actions depending on it. Those actions might include logging the exception, redirecting the user to another page or rendering specialized diff --git a/event_dispatcher.rst b/event_dispatcher.rst index 5fa38654681..ebe203e5ee6 100644 --- a/event_dispatcher.rst +++ b/event_dispatcher.rst @@ -1,5 +1,286 @@ -Event Dispatcher -================ +.. index:: + single: Events; Create listener + single: Create subscriber + +Events and Event Listeners +========================== + +During the execution of a Symfony application, lots of event notifications are +triggered. Your application can listen to these notifications and respond to +them by executing any piece of code. + +Internal events provided by Symfony itself are defined in the +:class:`Symfony\\Component\\HttpKernel\\KernelEvents` class. Third-party bundles +and libraries also trigger lots of events and your own application can trigger +:doc:`custom events `. + +All the examples shown in this article use the same ``KernelEvents::EXCEPTION`` +event for consistency purposes. In your own application, you can use any event +and even mix several of them in the same subscriber. + +Creating an Event Listener +-------------------------- + +The most common way to listen to an event is to register an **event listener**:: + + // src/AppBundle/EventListener/ExceptionListener.php + namespace AppBundle\EventListener; + + use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent; + use Symfony\Component\HttpFoundation\Response; + use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface; + + class ExceptionListener + { + public function onKernelException(GetResponseForExceptionEvent $event) + { + // You get the exception object from the received event + $exception = $event->getException(); + $message = sprintf( + 'My Error says: %s with code: %s', + $exception->getMessage(), + $exception->getCode() + ); + + // Customize your response object to display the exception details + $response = new Response(); + $response->setContent($message); + + // HttpExceptionInterface is a special type of exception that + // holds status code and header details + if ($exception instanceof HttpExceptionInterface) { + $response->setStatusCode($exception->getStatusCode()); + $response->headers->replace($exception->getHeaders()); + } else { + $response->setStatusCode(Response::HTTP_INTERNAL_SERVER_ERROR); + } + + // Send the modified response object to the event + $event->setResponse($response); + } + } + +.. tip:: + + Each event receives a slightly different type of ``$event`` object. For + the ``kernel.exception`` event, it is :class:`Symfony\\Component\\HttpKernel\\Event\\GetResponseForExceptionEvent`. + To see what type of object each event listener receives, see :class:`Symfony\\Component\\HttpKernel\\KernelEvents` + or the documentation about the specific event you're listening to. + +Now that the class is created, you just need to register it as a service and +notify Symfony that it is a "listener" on the ``kernel.exception`` event by +using a special "tag": + +.. configuration-block:: + + .. code-block:: yaml + + # app/config/services.yml + services: + app.exception_listener: + class: AppBundle\EventListener\ExceptionListener + tags: + - { name: kernel.event_listener, event: kernel.exception } + + .. code-block:: xml + + + + + + + + + + + + + + .. code-block:: php + + // app/config/services.php + $container + ->register('app.exception_listener', 'AppBundle\EventListener\ExceptionListener') + ->addTag('kernel.event_listener', array('event' => 'kernel.exception')) + ; + +.. note:: + + There is an optional tag attribute called ``method`` which defines which method + to execute when the event is triggered. By default the name of the method is + ``on`` + "camel-cased event name". If the event is ``kernel.exception`` the + method executed by default is ``onKernelException()``. + + The other optional tag attribute is called ``priority``, which defaults to + ``0`` and it controls the order in which listeners are executed (the highest + the priority, the earlier a listener is executed). This is useful when you + need to guarantee that one listener is executed before another. The priorities + of the internal Symfony listeners usually range from ``-255`` to ``255`` but + your own listeners can use any positive or negative integer. + +Creating an Event Subscriber +---------------------------- + +Another way to listen to events is via an **event subscriber**, which is a class +that defines one or more methods that listen to one or various events. The main +difference with the event listeners is that subscribers always know which events +they are listening to. + +In a given subscriber, different methods can listen to the same event. The order +in which methods are executed is defined by the ``priority`` parameter of each +method (the higher the priority the earlier the method is called). To learn more +about event subscribers, read :doc:`/components/event_dispatcher`. + +The following example shows an event subscriber that defines several methods which +listen to the same ``kernel.exception`` event:: + + // src/AppBundle/EventSubscriber/ExceptionSubscriber.php + namespace AppBundle\EventSubscriber; + + use Symfony\Component\EventDispatcher\EventSubscriberInterface; + use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent; + use Symfony\Component\HttpKernel\KernelEvents; + + class ExceptionSubscriber implements EventSubscriberInterface + { + public static function getSubscribedEvents() + { + // return the subscribed events, their methods and priorities + return array( + KernelEvents::EXCEPTION => array( + array('processException', 10), + array('logException', 0), + array('notifyException', -10), + ) + ); + } + + public function processException(GetResponseForExceptionEvent $event) + { + // ... + } + + public function logException(GetResponseForExceptionEvent $event) + { + // ... + } + + public function notifyException(GetResponseForExceptionEvent $event) + { + // ... + } + } + +Now, you just need to register the class as a service and add the +``kernel.event_subscriber`` tag to tell Symfony that this is an event subscriber: + +.. configuration-block:: + + .. code-block:: yaml + + # app/config/services.yml + services: + app.exception_subscriber: + class: AppBundle\EventSubscriber\ExceptionSubscriber + tags: + - { name: kernel.event_subscriber } + + .. code-block:: xml + + + + + + + + + + + + + + .. code-block:: php + + // app/config/services.php + $container + ->register( + 'app.exception_subscriber', + 'AppBundle\EventSubscriber\ExceptionSubscriber' + ) + ->addTag('kernel.event_subscriber') + ; + +Request Events, Checking Types +------------------------------ + +A single page can make several requests (one master request, and then multiple +sub-requests - typically by :doc:`/templating/embedding_controllers`). For the core +Symfony events, you might need to check to see if the event is for a "master" request +or a "sub request":: + + // src/AppBundle/EventListener/RequestListener.php + namespace AppBundle\EventListener; + + use Symfony\Component\HttpKernel\Event\GetResponseEvent; + use Symfony\Component\HttpKernel\HttpKernel; + use Symfony\Component\HttpKernel\HttpKernelInterface; + + class RequestListener + { + public function onKernelRequest(GetResponseEvent $event) + { + if (!$event->isMasterRequest()) { + // don't do anything if it's not the master request + return; + } + + // ... + } + } + +Certain things, like checking information on the *real* request, may not need to +be done on the sub-request listeners. + +.. _events-or-subscribers: + +Listeners or Subscribers +------------------------ + +Listeners and subscribers can be used in the same application indistinctly. The +decision to use either of them is usually a matter of personal taste. However, +there are some minor advantages for each of them: + +* **Subscribers are easier to reuse** because the knowledge of the events is kept + in the class rather than in the service definition. This is the reason why + Symfony uses subscribers internally; +* **Listeners are more flexible** because bundles can enable or disable each of + them conditionally depending on some configuration value. + +Debugging Event Listeners +------------------------- + +.. versionadded:: 2.6 + The ``debug:event-dispatcher`` command was introduced in Symfony 2.6. + +You can find out what listeners are registered in the event dispatcher +using the console. To show all events and their listeners, run: + +.. code-block:: bash + + $ php app/console debug:event-dispatcher + +You can get registered listeners for a particular event by specifying +its name: + +.. code-block:: bash + + $ php app/console debug:event-dispatcher kernel.exception .. toctree:: :maxdepth: 1 diff --git a/event_dispatcher/before_after_filters.rst b/event_dispatcher/before_after_filters.rst index b282159e638..eb171b4e9ca 100644 --- a/event_dispatcher/before_after_filters.rst +++ b/event_dispatcher/before_after_filters.rst @@ -102,7 +102,7 @@ Creating an Event Listener Next, you'll need to create an event listener, which will hold the logic that you want executed before your controllers. If you're not familiar with -event listeners, you can learn more about them at :doc:`/event_dispatcher/event_listener`:: +event listeners, you can learn more about them at :doc:`/event_dispatcher`:: // src/AppBundle/EventListener/TokenListener.php namespace AppBundle\EventListener; diff --git a/event_dispatcher/event_listener.rst b/event_dispatcher/event_listener.rst deleted file mode 100644 index 6f55c98554c..00000000000 --- a/event_dispatcher/event_listener.rst +++ /dev/null @@ -1,283 +0,0 @@ -.. index:: - single: Events; Create listener - single: Create subscriber - -How to Create Event Listeners and Subscribers -============================================= - -During the execution of a Symfony application, lots of event notifications are -triggered. Your application can listen to these notifications and respond to -them by executing any piece of code. - -Internal events provided by Symfony itself are defined in the -:class:`Symfony\\Component\\HttpKernel\\KernelEvents` class. Third-party bundles -and libraries also trigger lots of events and your own application can trigger -:doc:`custom events `. - -All the examples shown in this article use the same ``KernelEvents::EXCEPTION`` -event for consistency purposes. In your own application, you can use any event -and even mix several of them in the same subscriber. - -Creating an Event Listener --------------------------- - -The most common way to listen to an event is to register an **event listener**:: - - // src/AppBundle/EventListener/ExceptionListener.php - namespace AppBundle\EventListener; - - use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent; - use Symfony\Component\HttpFoundation\Response; - use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface; - - class ExceptionListener - { - public function onKernelException(GetResponseForExceptionEvent $event) - { - // You get the exception object from the received event - $exception = $event->getException(); - $message = sprintf( - 'My Error says: %s with code: %s', - $exception->getMessage(), - $exception->getCode() - ); - - // Customize your response object to display the exception details - $response = new Response(); - $response->setContent($message); - - // HttpExceptionInterface is a special type of exception that - // holds status code and header details - if ($exception instanceof HttpExceptionInterface) { - $response->setStatusCode($exception->getStatusCode()); - $response->headers->replace($exception->getHeaders()); - } else { - $response->setStatusCode(Response::HTTP_INTERNAL_SERVER_ERROR); - } - - // Send the modified response object to the event - $event->setResponse($response); - } - } - -.. tip:: - - Each event receives a slightly different type of ``$event`` object. For - the ``kernel.exception`` event, it is :class:`Symfony\\Component\\HttpKernel\\Event\\GetResponseForExceptionEvent`. - To see what type of object each event listener receives, see :class:`Symfony\\Component\\HttpKernel\\KernelEvents` - or the documentation about the specific event you're listening to. - -Now that the class is created, you just need to register it as a service and -notify Symfony that it is a "listener" on the ``kernel.exception`` event by -using a special "tag": - -.. configuration-block:: - - .. code-block:: yaml - - # app/config/services.yml - services: - app.exception_listener: - class: AppBundle\EventListener\ExceptionListener - tags: - - { name: kernel.event_listener, event: kernel.exception } - - .. code-block:: xml - - - - - - - - - - - - - - .. code-block:: php - - // app/config/services.php - $container - ->register('app.exception_listener', 'AppBundle\EventListener\ExceptionListener') - ->addTag('kernel.event_listener', array('event' => 'kernel.exception')) - ; - -.. note:: - - There is an optional tag attribute called ``method`` which defines which method - to execute when the event is triggered. By default the name of the method is - ``on`` + "camel-cased event name". If the event is ``kernel.exception`` the - method executed by default is ``onKernelException()``. - - The other optional tag attribute is called ``priority``, which defaults to - ``0`` and it controls the order in which listeners are executed (the highest - the priority, the earlier a listener is executed). This is useful when you - need to guarantee that one listener is executed before another. The priorities - of the internal Symfony listeners usually range from ``-255`` to ``255`` but - your own listeners can use any positive or negative integer. - -Creating an Event Subscriber ----------------------------- - -Another way to listen to events is via an **event subscriber**, which is a class -that defines one or more methods that listen to one or various events. The main -difference with the event listeners is that subscribers always know which events -they are listening to. - -In a given subscriber, different methods can listen to the same event. The order -in which methods are executed is defined by the ``priority`` parameter of each -method (the higher the priority the earlier the method is called). To learn more -about event subscribers, read :doc:`/components/event_dispatcher`. - -The following example shows an event subscriber that defines several methods which -listen to the same ``kernel.exception`` event:: - - // src/AppBundle/EventSubscriber/ExceptionSubscriber.php - namespace AppBundle\EventSubscriber; - - use Symfony\Component\EventDispatcher\EventSubscriberInterface; - use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent; - use Symfony\Component\HttpKernel\KernelEvents; - - class ExceptionSubscriber implements EventSubscriberInterface - { - public static function getSubscribedEvents() - { - // return the subscribed events, their methods and priorities - return array( - KernelEvents::EXCEPTION => array( - array('processException', 10), - array('logException', 0), - array('notifyException', -10), - ) - ); - } - - public function processException(GetResponseForExceptionEvent $event) - { - // ... - } - - public function logException(GetResponseForExceptionEvent $event) - { - // ... - } - - public function notifyException(GetResponseForExceptionEvent $event) - { - // ... - } - } - -Now, you just need to register the class as a service and add the -``kernel.event_subscriber`` tag to tell Symfony that this is an event subscriber: - -.. configuration-block:: - - .. code-block:: yaml - - # app/config/services.yml - services: - app.exception_subscriber: - class: AppBundle\EventSubscriber\ExceptionSubscriber - tags: - - { name: kernel.event_subscriber } - - .. code-block:: xml - - - - - - - - - - - - - - .. code-block:: php - - // app/config/services.php - $container - ->register( - 'app.exception_subscriber', - 'AppBundle\EventSubscriber\ExceptionSubscriber' - ) - ->addTag('kernel.event_subscriber') - ; - -Request Events, Checking Types ------------------------------- - -A single page can make several requests (one master request, and then multiple -sub-requests - typically by :doc:`/templating/embedding_controllers`). For the core -Symfony events, you might need to check to see if the event is for a "master" request -or a "sub request":: - - // src/AppBundle/EventListener/RequestListener.php - namespace AppBundle\EventListener; - - use Symfony\Component\HttpKernel\Event\GetResponseEvent; - use Symfony\Component\HttpKernel\HttpKernel; - use Symfony\Component\HttpKernel\HttpKernelInterface; - - class RequestListener - { - public function onKernelRequest(GetResponseEvent $event) - { - if (!$event->isMasterRequest()) { - // don't do anything if it's not the master request - return; - } - - // ... - } - } - -Certain things, like checking information on the *real* request, may not need to -be done on the sub-request listeners. - -.. _events-or-subscribers: - -Listeners or Subscribers ------------------------- - -Listeners and subscribers can be used in the same application indistinctly. The -decision to use either of them is usually a matter of personal taste. However, -there are some minor advantages for each of them: - -* **Subscribers are easier to reuse** because the knowledge of the events is kept - in the class rather than in the service definition. This is the reason why - Symfony uses subscribers internally; -* **Listeners are more flexible** because bundles can enable or disable each of - them conditionally depending on some configuration value. - -Debugging Event Listeners -------------------------- - -.. versionadded:: 2.6 - The ``debug:event-dispatcher`` command was introduced in Symfony 2.6. - -You can find out what listeners are registered in the event dispatcher -using the console. To show all events and their listeners, run: - -.. code-block:: bash - - $ php app/console debug:event-dispatcher - -You can get registered listeners for a particular event by specifying -its name: - -.. code-block:: bash - - $ php app/console debug:event-dispatcher kernel.exception diff --git a/reference/dic_tags.rst b/reference/dic_tags.rst index fe13a06a9a7..953e0397a65 100644 --- a/reference/dic_tags.rst +++ b/reference/dic_tags.rst @@ -583,8 +583,8 @@ During the execution of a Symfony application, different events are triggered and you can also dispatch custom events. This tag allows you to *hook* your own classes into any of those events. -For a full example of this listener, read the :doc:`/event_dispatcher/event_listener` -cookbook entry. +For a full example of this listener, read the :doc:`/event_dispatcher` +article. Core Event Listener Reference ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/session/locale_sticky_session.rst b/session/locale_sticky_session.rst index 2a6db85d1e1..d9d96c4cb4e 100644 --- a/session/locale_sticky_session.rst +++ b/session/locale_sticky_session.rst @@ -14,7 +14,7 @@ Creating a LocaleListener ------------------------- To simulate that the locale is stored in a session, you need to create and -register a :doc:`new event listener `. +register a :doc:`new event listener `. The listener will look something like this. Typically, ``_locale`` is used as a routing parameter to signify the locale, though it doesn't really matter how you determine the desired locale from the request::