Creare un ascoltatore di eventi

Symfony dispone di vari eventi e agganci, che si possono usare per far scattare comportamenti personalizzati in un’applicazione. Questi eventi sono lanciati dal componente HttpKernel e possono essere visualizzati nella classe Symfony\Component\HttpKernel\KernelEvents.

Per agganciarsi a un evento e aggiungere la propria logica, occorre creare un servizio che agisca da ascoltatore su tale evento. In questa ricetta, creeremo un servizio che agirà da ascoltatore di eccezioni, consentendo di modificare il modo in cui sono mostrare le eccezioni nella nostra applicazione. L’evento KernelEvents::EXCEPTION è solo uno degli eventi del nucleo:

// src/AppBundle/EventListener/AcmeExceptionListener.php
namespace AppBundle\EventListener;

use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface;

class AcmeExceptionListener
{
    public function onKernelException(GetResponseForExceptionEvent $event)
    {
        // Prende l'oggetto eccezione dall'evento ricevuto
        $exception = $event->getException();
        $message = sprintf(
            'Il mio errore dice: %s con codice: %s',
            $exception->getMessage(),
            $exception->getCode()
        );

        // Personalizza l'oggetto risposta per mostrare i dettagli sull'eccezione
        $response = new Response();
        $response->setContent($message);

        // HttpExceptionInterface è un tipo speciale di eccezione, che
        // contiene il codice di stato e altri dettagli sugli header
        if ($exception instanceof HttpExceptionInterface) {
            $response->setStatusCode($exception->getStatusCode());
            $response->headers->replace($exception->getHeaders());
        } else {
            $response->setStatusCode(Response::HTTP_INTERNAL_SERVER_ERROR);
        }

        // Invia la risposta modificata all'evento
        $event->setResponse($response);
    }
}

Nuovo nella versione 2.4: Il supporto per le costanti dei codici di stato HTTP è stato introdotto in Symfony 2.4.

Suggerimento

Ciascun ascoltatore riceve un tipo leggermente diverso di oggetto $event. Per esempio, l’evento kernel.exception è un Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent. Per vedere il tipo di oggetto ricevuto da un ascoltatore, si veda Symfony\Component\HttpKernel\KernelEvents.

Dopo aver creato la classe, basta registrarla come servizio e notificare a Symfony che è un ascoltatore dell’evento kernel.exception, usando un particolare tag:

  • YAML
    # app/config/services.yml
    services:
        kernel.listener.nome_ascoltatore:
            class: AppBundle\EventListener\AcmeExceptionListener
            tags:
                - { name: kernel.event_listener, event: kernel.exception, method: onKernelException }
    
  • XML
    <!-- app/config/services.xml -->
    <service id="kernel.listener.nome_ascoltatore" class="AppBundle\EventListener\AcmeExceptionListener">
        <tag name="kernel.event_listener" event="kernel.exception" method="onKernelException" />
    </service>
    
  • PHP
    // app/config/services.php
    $container
        ->register('kernel.listener.nome_ascoltatore', 'AppBundle\EventListener\AcmeExceptionListener')
        ->addTag('kernel.event_listener', array('event' => 'kernel.exception', 'method' => 'onKernelException'))
    ;
    

Nota

C’è un’ulteriore opzione del tag, priority, facoltativa e con valore predefinito 0. Questo valore può essere da -255 a 255 e gli ascoltatori saranno eseguiti con un ordine basato sulla loro priorità. Questo è utile quando occorre assicurarsi che un ascoltatore sia eseguito prima di un altro.

Eventi richiesta, verifica dei tipi

Nuovo nella versione 2.4: Il metodo isMasterRequest() è stato introdotto in Symfony 2.4. In precedenza veniva usato il metodo getRequestType().

Una singola pagina può eseguire diverse richieste (una principale e poi diverse sotto-richieste); per questo, quando si ha a che fare con l’evento KernelEvents::REQUEST, si potrebbe voler verificare il tipo di richiesta. Lo si può fare facilmente, come segue:

// src/AppBundle/EventListener/AcmeRequestListener.php
namespace AppBundle\EventListener;

use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\HttpKernel\HttpKernel;

class AcmeRequestListener
{
    public function onKernelRequest(GetResponseEvent $event)
    {
        if (!$event->isMasterRequest()) {
            // non fare niente se non si è nella richiesta principale
            return;
        }

        // ...
    }
}

Suggerimento

Sono disponibili due tipi di richiesta nell’interfaccia Symfony\Component\HttpKernel\HttpKernelInterface: HttpKernelInterface::MASTER_REQUEST e HttpKernelInterface::SUB_REQUEST.

Tabella dei contenuti

Argomento precedente

Contenitore di servizi

Argomento successivo

Lavorare con gli scope

Questa pagina