亚洲国产日韩欧美一区二区三区,精品亚洲国产成人av在线,国产99视频精品免视看7,99国产精品久久久久久久成人热,欧美日韩亚洲国产综合乱

Symfony2 ??? ??? / 事件和事件監(jiān)聽(tīng)

事件和事件監(jiān)聽(tīng)

在symfony程序執(zhí)行期間,大量的事件通知(event notifications)會(huì)被觸發(fā)。你的程序可以監(jiān)聽(tīng)這些通知,并執(zhí)行任意代碼作為回應(yīng)。

Symfony自身提供的內(nèi)部事件,被定義在KernelEvents類中。第三方Bundle和類庫(kù)也會(huì)觸發(fā)大量事件,你自己的程序可以觸發(fā)自定義事件。

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

創(chuàng)建一個(gè)事件監(jiān)聽(tīng) ?

監(jiān)聽(tīng)一個(gè)事件最常用的方式是注冊(cè)一個(gè)事件監(jiān)聽(tīng)(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
        // 你可以從接收到的事件中,取得異常對(duì)象
        $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
        // 自定義響應(yīng)對(duì)象,來(lái)顯示異常的細(xì)節(jié)
        $response = new Response();
        $response->setContent($message);         // HttpExceptionInterface is a special type of exception that
        // holds status code and header details
        // HttpExceptionInterface是一個(gè)特殊類型的異常,持有狀態(tài)碼和頭信息的細(xì)節(jié)
        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
        // 發(fā)送修改后的響應(yīng)對(duì)象到事件中
        $event->setResponse($response);
    }}


每一個(gè)事件,都要接收“類型略有不同”的$event對(duì)象。對(duì)于kernel.exception事件,這個(gè)對(duì)象是GetResponseForExceptionEvent。要了解每一個(gè)“事件監(jiān)聽(tīng)”所接收到的“事件對(duì)象”之類型,參考KernelEvents,或是你要監(jiān)聽(tīng)的特定事件之文檔。


現(xiàn)在,類被創(chuàng)建了,你只需把它注冊(cè)成服務(wù),然后通過(guò)使用一個(gè)特殊的“tag”(標(biāo)簽),告訴Symfony這是一個(gè)針對(duì)kernel.exception事件的“監(jiān)聽(tīng)”:

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'));

有一個(gè)可選的tag屬性是method,它定義了“當(dāng)事件被觸發(fā)時(shí),哪個(gè)方法要被執(zhí)行”。默認(rèn)時(shí),方法的名字是on+“駝峰事件名”。如果事件是kernel.exception的話,默認(rèn)執(zhí)行的方法則是onKernelException()。

另有一個(gè)可選的tag屬性是priority,它的默認(rèn)值是0,用來(lái)控制監(jiān)聽(tīng)被執(zhí)行的順序(一個(gè)監(jiān)聽(tīng)器的優(yōu)先級(jí)愈高則愈早被執(zhí)行)。這在你要“確保某個(gè)監(jiān)聽(tīng)在其他監(jiān)聽(tīng)之前被執(zhí)行”時(shí)是有用的。Symfony的內(nèi)部監(jiān)聽(tīng),其優(yōu)先級(jí)范圍是-255255,但你自己的監(jiān)聽(tīng)可以使用任何正或負(fù)的整數(shù)。

創(chuàng)建一個(gè)事件訂閱 ?

另一種監(jiān)聽(tīng)事件的方式是event subscriber事件訂閱,它是一個(gè)類,定義了一或多個(gè)方法,用于監(jiān)聽(tīng)一或多個(gè)事件。同事件監(jiān)聽(tīng)的主要區(qū)別在于,訂閱器始終知道它們正在監(jiān)聽(tīng)的事件是哪一個(gè)。

在一個(gè)給定的訂閱器中,不同的方法可以監(jiān)聽(tīng)同一個(gè)事件。方法被執(zhí)行時(shí)的順序,通過(guò)每一個(gè)方法中的priority參數(shù)來(lái)定義(優(yōu)先級(jí)愈高則方法愈早被調(diào)用)。要了解更多關(guān)于訂閱器的內(nèi)容,參考EventDispatcher組件

下例展示了一個(gè)事件訂閱,定義了若干方法,監(jiān)聽(tīng)的是同一個(gè)kernel.exception事件:

// 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)
    {
        // ...
    }}

現(xiàn)在,你只需把這個(gè)類注冊(cè)成服務(wù),并打上kernel.event_subscriber標(biāo)簽,即可告訴Symofny這是一個(gè)事件訂閱器:

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 }

Request事件,檢查T(mén)ype ?

一個(gè)單一頁(yè)面,可以產(chǎn)生若干次請(qǐng)求(一個(gè)主請(qǐng)求[master request],然后是多個(gè)子請(qǐng)求[sub-requests],典型的像是如何在模板中嵌入控制器)。對(duì)于Symfony核心事件,你可能需要檢查一下,看這個(gè)事件是一個(gè)“主”請(qǐng)求還是一個(gè)“子”請(qǐng)求:

// 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
            // 如果不是主請(qǐng)求,就什么也不做
            return;
        }         // ...
    }}

特定行為,像是對(duì)真正的請(qǐng)求進(jìn)行檢查這種,可能并不需要在子請(qǐng)求的監(jiān)聽(tīng)中進(jìn)行。

監(jiān)聽(tīng)還是訂閱 ?

監(jiān)聽(tīng)器和訂閱器,在同一程序中使用時(shí),可能界限模糊。決定使用哪一種,通常由個(gè)人口味決定。但是,每種都有各自的優(yōu)點(diǎn):

  • 訂閱器易于復(fù)用,因?yàn)榕c事件有關(guān)的內(nèi)容存在于類中,而不是存在于服務(wù)定義中。這導(dǎo)致Symfony內(nèi)部使用訂閱器;

  • 監(jiān)聽(tīng)器更靈活,因?yàn)閎undles可以有條件地開(kāi)啟或關(guān)閉它們,基于配置文件中的某些“選項(xiàng)值”。

對(duì)事件監(jiān)聽(tīng)器進(jìn)行調(diào)試 ?

使用命令行,你可以找到“哪些監(jiān)聽(tīng)被注冊(cè)到事件派遣器”。要顯示全部事件及其監(jiān)聽(tīng),運(yùn)行:

1
$  php bin/console debug:event-dispatcher

通過(guò)指定事件名稱,你可以得到針對(duì)此特定事件進(jìn)行注冊(cè)的監(jiān)聽(tīng):

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