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




    4 Comentarios

    1. Argelio

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

      Responder
    2. sedlav

      @Argelio no entiendo tu pregunta

      Responder
    3. Argelio

      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

      Responder
    4. sedlav

      Esta hecho usando symfony2 (PHP) no necesitas Java

      Responder

    Dejar un comentario

    Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *