Événements et écoute d'événements


Lors de l'exécution du programme symfony, un grand nombre de notifications d'événements seront déclenchées. Votre programme peut écouter ces notifications et exécuter du code arbitraire en réponse.

Les événements internes fournis par Symfony lui-même sont définis dans KernelEvents. Les bundles tiers et les bibliothèques de classes déclencheront également un grand nombre d'événements, et votre propre programme peut déclencher des événements personnalisés. KernelEvents类中。第三方Bundle和类库也会触发大量事件,你自己的程序可以触发自定义事件

本文展示的所有例子,考虑到一致性,使用了相同的KernelEvents::EXCEPTION事件。在你自己的程序中,你可以使用任何事件,甚至在同一订阅器中(subscriber)混合若干事件。

创建一个事件监听 

监听一个事件最常用的方式是注册一个事件监听(event listener)

// src/AppBundle/EventListener/ExceptionListener.phpnamespace 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
        // HttpExceptionInterface是一个特殊类型的异常,持有状态码和头信息的细节
        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);
    }}


每一个事件,都要接收“类型略有不同”的$event对象。对于kernel.exception事件,这个对象是GetResponseForExceptionEvent。要了解每一个“事件监听”所接收到的“事件对象”之类型,参考KernelEvents,或是你要监听的特定事件之文档。


现在,类被创建了,你只需把它注册成服务,然后通过使用一个特殊的“tag”(标签),告诉Symfony这是一个针对kernel.exception事件的“监听”:

YAML:# app/config/services.ymlservices:
    app.exception_listener:
        class: AppBundle\EventListener\ExceptionListener
        tags:
            - { name: kernel.event_listener, event: kernel.exception }
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">     <services>
        <service id="app.exception_listener"            class="AppBundle\EventListener\ExceptionListener">             <tag name="kernel.event_listener" event="kernel.exception" />
        </service>
    </services></container>
php:// app/config/services.php$container
    ->register('app.exception_listener', 'AppBundle\EventListener\ExceptionListener')
    ->addTag('kernel.event_listener', array('event' => 'kernel.exception'));

有一个可选的tag属性是method,它定义了“当事件被触发时,哪个方法要被执行”。默认时,方法的名字是on+“驼峰事件名”。如果事件是kernel.exception的话,默认执行的方法则是onKernelException()

另有一个可选的tag属性是priority,它的默认值是0,用来控制监听被执行的顺序(一个监听器的优先级愈高则愈早被执行)。这在你要“确保某个监听在其他监听之前被执行”时是有用的。Symfony的内部监听,其优先级范围是-255255

Tous les exemples présentés dans cet article, en tenant compte de la cohérence, utilisent le même événement KernelEvents::EXCEPTION. Dans votre propre programme, vous pouvez utiliser n'importe quel événement et même mélanger plusieurs événements chez un même abonné.

Créer un écouteur d'événement

La façon la plus courante d'écouter un événement est d'enregistrer un event Écouteur d'événement : 🎜
// src/AppBundle/EventSubscriber/ExceptionSubscriber.phpnamespace 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)
    {
        // ...
    }}
🎜
🎜
🎜Chaque événement doit recevoir un "type légèrement différent" $event Objet. Pour l'événement kernel.exception, cet objet est GetResponseForExceptionEvent. Pour comprendre le type d'"objet événement" reçu par chaque "écouteur d'événement", reportez-vous à KernelEvents< / a>, ou le document correspondant à l'événement spécifique que vous souhaitez écouter. 🎜🎜🎜
🎜🎜Maintenant que la classe est créée, il vous suffit de l'enregistrer en tant que service puis d'indiquer à Symfony qu'il s'agit d'une cible pour kernel.exception en utilisant une "tag" spéciale Événement "écoute" : 🎜
PHP:// app/config/services.php$container
    ->register(
        'app.exception_subscriber',
        'AppBundle\EventSubscriber\ExceptionSubscriber'
    )
    ->addTag('kernel.event_subscriber');
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">     <services>
        <service id="app.exception_subscriber"            class="AppBundle\EventSubscriber\ExceptionSubscriber">             <tag name="kernel.event_subscriber"/>
        </service>
    </services></container>
YAML:# app/config/services.ymlservices:
    app.exception_subscriber:
        class: AppBundle\EventSubscriber\ExceptionSubscriber
        tags:
            - { name: kernel.event_subscriber }
🎜 a un attribut de balise facultatif qui est la méthode , qui définit "quelle méthode doit être exécutée lorsque l'événement est déclenché". Par défaut, le nom de la méthode est on+"nom de l'événement camel case". Si l'événement est kernel.exception, la méthode d'exécution par défaut est onKernelException().
🎜🎜Un autre attribut de balise facultatif est priority, sa valeur par défaut est 0, qui est utilisée pour contrôler l'ordre dans lequel l'écouteur est exécuté (un écouteur Le plus la priorité est élevée, plus il sera exécuté tôt). Ceci est utile lorsque vous souhaitez vous assurer qu'un écouteur est exécuté avant les autres auditeurs. Les auditeurs internes de Symfony ont une plage de priorité allant de -255 à 255, mais vos propres auditeurs peuvent utiliser n'importe quel entier positif ou négatif. 🎜🎜🎜

Créer un abonnement à un événement

Une autre façon d'écouter des événements est abonné à un événementAbonnement à un événement, qui est une classe qui définit une ou plusieurs méthodes pour écouter un ou plusieurs événements. La principale différence avec l’écoute d’événements est que les abonnés savent toujours quel événement ils écoutent.

Chez un abonné donné, différentes méthodes peuvent écouter le même événement. L'ordre dans lequel les méthodes sont exécutées est défini par le paramètre priority dans chaque méthode (plus la priorité est élevée, plus la méthode est appelée tôt). Pour en savoir plus sur les abonnés, reportez-vous au composant EventDispatcherpriority参数来定义(优先级愈高则方法愈早被调用)。要了解更多关于订阅器的内容,参考EventDispatcher组件

下例展示了一个事件订阅,定义了若干方法,监听的是同一个kernel.exception事件:

// src/AppBundle/EventListener/RequestListener.phpnamespace 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;
        }         // ...
    }}

现在,你只需把这个类注册成服务,并打上kernel.event_subscriber.

L'exemple suivant montre un abonnement à un événement, qui définit plusieurs méthodes et écoute le même événement kernel.exception :

1
Maintenant, il vous suffit d'enregistrer cette classe en tant que service et de marquer < code La balise >kernel.event_subscriber
peut indiquer à Symofny qu'il s'agit d'un abonné à un événement :

$  php bin/console debug:event-dispatcher
1
$  php bin/console debug:event-dispatcher kernel.exception

Request event, vérifiez le Type

Une seule page peut générer plusieurs requêtes (une requête principale [ master request], puis plusieurs sous-requêtes [sous-requêtes], généralement comme Comment intégrer un contrôleur dans un modèle). Pour les événements principaux de Symfony, vous souhaiterez peut-être vérifier si l'événement est une requête « principale » ou une requête « secondaire » :
rrreee

Des actions spécifiques, comme la vérification des

réellesrequêtes, peuvent ne pas être nécessaires. Effectuées lors de l'écoute. de sous-requêtes.

Écouter ou s'abonner

  • Les auditeurs et les abonnés peuvent avoir des frontières floues lorsqu'ils sont utilisés dans le même programme. Décider lequel utiliser dépend souvent de vos goûts personnels. Cependant, chacun a ses propres avantages :

  • Les abonnés sont faciles à réutiliser

    car le contenu lié à l'événement vit dans la classe, pas dans la définition du service. Cela fait que Symfony utilise les abonnés en interne ;

les auditeurs sont plus flexibles

car les bundles peuvent les activer ou les désactiver de manière conditionnelle, en fonction de certaines "valeurs d'option" dans le fichier de configuration.

Déboguer les écouteurs d'événements

En utilisant la ligne de commande, vous pouvez trouver "quels écouteurs sont enregistrés auprès du répartiteur d'événements". Pour afficher tous les événements et leurs auditeurs, exécutez : rrreee
rrreee
🎜🎜🎜🎜

En précisant le nom de l'événement, vous pouvez obtenir les auditeurs inscrits à cet événement spécifique :

rrreee
rrreee