Creando un Listener en Symfony2

Este artículo forma parte de la serie Symfony2 y presupone que Ud. ha:

- Instalado y configurado Symfony2 Standard Edition, se recomienda leer: Instalando y configurando Symfony2 en un ambiente compartido

- Instalado y configurado APC se recomienda leer: Instalar Alternative PHP Cache (APC) en CentOS

Partamos de la idea de que estamos desarrollando una API Restful y que deseamos cachear las respuestas de cada acción ejecutada en los Controladores (Controller), para ello:

Configuramos el Listener en nuestro config.yml

...
services:
  # Identificador del Listener 
  request.listener:
    # Listener Namespace and nombre de la clase
    class: AcmeDemoBundleEventListenerRequestListener
    # Inyección de dependencia: Contenedor de servicios 
    calls:
        - [ setContainer, [ @service_container ] ]
    # Definición del servicio como Listener: los eventos a observar son kernel.request (cada vez que se realiza una
    # petición Http), KernelResponse (cada vez que se devuelve una respuesta a la petición Http), kernel.exception 
    # (cada vez que ocurre una excepción)
    tags:
        - { name: kernel.event_listener, event: kernel.request, method: onKernelRequest }
        - { name: kernel.event_listener, event: kernel.exception, method: onKernelException }
        - { name: kernel.event_listener, event: kernel.response, method: onKernelResponse }
...

Crear dir EventListener dentro de AcmeDemoBundle

$ mkdir src/Acme/DemoBundle/EventListener

Crear Listener

Nuestra clase debe implementar la interfaz ContainerAwareInterface

class RequestListener implements ContainerAwareInterface

Inyectamos el contenedor de servicios

/**
 * @var ContainerInterface
 */
 protected $container;

 public function setContainer(ContainerInterface $container = null)
 {
     $this->container = $container;
 }

Verificamos si existe un Objeto Response cacheado para la Petición correspondiente

/**
 * This method is executed for every Http Request. If the content is found
 * in Apc Cache the execution flow is stopped and a Response is returned
 * inmediately, no controller action is executed.
 * @param GetResponseEvent $event
 * @return type
 */
public function onKernelRequest(GetResponseEvent $event)
{
    // No caching for dev enviroment
    if ($this->container->getParameter('kernel.environment') === 'dev') {
        return;
    }

    $request = $event->getRequest();

    // Cahing only for Http Get method
    if ('GET' !== $request->getMethod()) {
        return;
    }

    // Build Apc cache key
    $path = 'controller.' . $request->getPathInfo();

    $qs = $request->getQueryString();

    // For caching request with query string if you do not aware of it
    // comment out
    if (!empty($qs)) {
        $path .= '.' . sha1($qs);
    }

    if (apc_exists($path)) {
        $event->setResponse(apc_fetch($path));
    }
}

Cacheamos el Objeto Response

/**
 * This method is executed after a Controller action and before the Response
 * is returned to the Browser or to another agent. Stores the Response object,
 * If it has not been cached
 *
 * @param FilterResponseEvent $event
 * @return type
 */
public function onKernelResponse(FilterResponseEvent $event)
{
    // No caching for dev enviroment
    if ($this->container->getParameter('kernel.environment') === 'dev') {
        return;
    }

    $request = $event->getRequest();

    // Cahing only for Http Get method
    if ('GET' !== $request->getMethod()) {
        return;
    }

    // Build Apc cache key
    $path = 'controller.' . $request->getPathInfo();

    // For caching request with query string if you do not aware of it
    // comment out
    $qs = $request->getQueryString();

    if (!empty($qs)) {
        $path .= '.' . sha1($qs);
    }

    if (!apc_exists($path)) {
        apc_store($path, $event->getResponse());
    }
}

Evitamos cachear las excepciones

/*
 * This method prevent to cache Response when occurs Exceptions
 */
public function onKernelException(GetResponseForExceptionEvent $event)
{
    $event->stopPropagation();
}

Verificamos que el listener ha sido registrado

$ php app/console container:debug
...
request.listener                            container AcmeDemoBundleEventListenerRequestListener
...

Ahora si ponemos en nuestro navegador:

- http://localhost/symfony-standard/web/app.php/demo/hello/World

e inspeccionamos la cache vemos lo siguiente.

APC

Puedes obtener la clase EventListener en:
Github

Lecturas recomendadas

Proyecto oficial Symfony2

Los tutoriales aquí en LibreByte están disponible bajo una licencia de software libre. Si le gusta mi trabajo considere:
Comprar un Hosting/VPS o Servidor Dedicado en MCKHost

4 comentarios

Saltar al formulario de comentarios

    • Argelio el noviembre 5, 2012 a las 12:12 pm
    • Responder

    disculpa pero en este momento estas programando en java? para enlazarlo a la base de datos ? saludos.

    • sedlav el noviembre 5, 2012 a las 2:38 pm
    • Responder

    @Argelio no entiendo tu pregunta

    • Argelio el noviembre 5, 2012 a las 2:41 pm
    • Responder

    lo que pasa es que necesito crear un listener para mi base de datos y no si el listener se crea en java? no se si me explico :s

    • sedlav el noviembre 6, 2012 a las 9:59 am
    • Responder

    Esta hecho usando symfony2 (PHP) no necesitas Java

Deja una respuesta

Tu dirección de correo electrónico no será publicada.

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.