Symfony2 – Redireccionando Error 404


Hoy empezamos el artículo con el siguiente error en Symfony2, por supuesto utilizando app_dev.php

No route found for “GET /Ruta”

Como claramente refiere es generado por una excepción del kernel cuando la ruta especificada no es encontrada en alguno de los ficheros de ruta de Symfony2.

En producción Symfony2 devuelve 404 correspondiente a que el host ha sido capaz de comunicarse con el servidor, pero no existe el fichero o ruta especificada. Por supuesto Symfony2 permite reemplazarlo por un 404 previamente modificado por nosotros pero eso es otro artículo.

Digamos que nuestra aplicación presenta como requisito que todos los errores 404 sean redireccionados al ROOT de nuestra aplicación, puede ser bien /Dashboard(Panel de Control), /Home(Inicio) o simplemente /(es la elegida en nuestro ejemplo)

Para ellos lo primero que debemos conocer es que Symfony2 maneja las excepciones pero deja siempre un mecanismo parecido a los Hooks de WordPress que nos ayuda a controlar diferentes situaciones con nuestra propia lógica. Para ello tenemos a nuestra disposición los servicios(services).

Los servicios nos permiten manejar excepciones actuando como Exception Listener en nuestra aplicación, cuando un evento determinado o excepción se activa el servicio se encarga de ejecutar nuestra lógica previamente establecida en una clase Listener cualquiera.

Para definir un servicio editamos el fichero de configuración app/config/config.yml. Si ya tenemos una sección services con servicios ya establecidos solo agregamos el nuevo, de lo contrario crearemos la sección como a continuación referimos.

services:
    kernel.listener.exception_listener:
        class: MyCyberAcademy\LeroyBundle\Listener\RedirectExceptionListener
        arguments: [@doctrine.orm.entity_manager, @logger]
        tags:
            - { name: kernel.event_listener, event: kernel.exception, method: checkRedirect }

La clase RedirectExceptionListener dentro de la carpeta Listener contiene la función con nuestra lógica(redireccionar a / en caso de no existir la ruta especificada). La sección arguments define parámetros de entrada a la función, en mi caso agrego el ORM en caso de necesitar realizar alguna transacción con la base de datos, por supuesto no es requerido. Seguidamente en cada excepción del kernel ejecutaremos el método checkRedirect que vemos a continuación.

<?php

namespace MyCyberAcademy\LeroyBundle\Listener;

use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Symfony\Component\HttpKernel\Log\LoggerInterface;
use Doctrine\ORM\EntityManager;

class RedirectExceptionListener
{
    /**
     * @var \Doctrine\ORM\EntityManager
     */
    protected $em;

    protected $logger;

    function __construct(EntityManager $em, LoggerInterface $logger)
    {
        $this->em = $em;
        $this->logger = $logger;
    }

    /**
     * @param \Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent $event
         */
        public function checkRedirect(GetResponseForExceptionEvent $event)
    {
        $exception = $event->getException();
        if ($exception instanceof NotFoundHttpException) {
                $event->setResponse(new RedirectResponse('/'));
        }
    }
}

Como pueden ver es una clase sencilla con solo una función checkRedirect la cual chequea si la excepción NotFoundHttpException fue istanciada como resultado de una URL no existente. Si es así redirecciona a la ruta especificada que como bien definimos se adapta a cualquier situación.

Symfony2 tiene una lista larga de excepciones que podemos chequear y establecer comportamientos diferentes, utilizando servicios y clases para ello, el mecanismo es el mismo. En los próximos artículos estaré brindando soluciones de este tipo a problemas cotidianos que pueden ser resueltos por propios mecanismos de Symfony2 que muchas veces no conocemos.

Latest posts by Leroy Ley (see all)