Este foro ya no está activo, así que no puedes publicar nuevas preguntas ni responder a las preguntas existentes.

Personalizar las páginas de error 404 en producción con Symfony

8 de septiembre de 2014

Buenos días comunidad!!,

Estoy dándole muchas vuelta a la hora de personalizar los errores 404 de Symfony. Mi version de Symfony es 2.4.8.

He hecho todo lo que he encontrado por internet y en la documentación:

Lo primero que he hecho es copiar todas las vista de TwigBundle a app/Resources/TwigBundle/views/Exceptions.

En modo debug lo que he modificado, me lo muestra bien (por ejemplo he cambiado el logo de Symfony por el mío corporativo y todo ok).

El problema viene cuando estoy en modo producción. Por ejemplo escribo en el navegador http://miapp.dev/mirutainventada. Y me muestra el tipico error:

Oops! An Error Occurred
 
The server returned a "404 Not Found".
 
Something is broken. Please e-mail us at [email] and let us know what you
were doing when this error occurred. We will fix it as soon as possible.
Sorry for any inconvenience caused.

El problema está que he cambiado tanto el archivo error.html.twig como el archivo error404.html.twig agregando una frase más. Pero nada, me sigue mostrando el mismo error. He borrado la cache con el comando app/console cache:clear --env=prod --no-debug. También me he ido al archivo prod.log y este es el mensaje que me muestra:

[2014-09-08 09:59:05] request.ERROR: Uncaught PHP Exception
Symfony\Component\HttpKernel\Exception\NotFoundHttpException: "No route found for "GET /asdasd"" at /Applications/AMPPS/www/symfony/app/cache/prod/classes.php line 1964 { "exception" : "[object] ( Symfony\Component\HttpKernel\Exception\NotFoundHttpException: No route found for \"GET /asdasd\" at /Applications/AMPPS/www/symfony/app/cache/prod/classes.php:1964, Symfony\Component\Routing\Exception\ResourceNotFoundException: at /Applications/AMPPS/www/symfony/app/cache/prod/appProdUrlMatcher.php:1289 )" } []

Espero puedan echarme un cable.

Un saludo.


Respuestas

#1

¡Hola @jcarlosweb!

Si me permites ser sincero contigo, creo que es un error tratar de personalizar cosas como el logotipo de Symfony de las páginas de excepciones en el entorno de desarrollo.

El principal motivo es que estas plantillas se suelen actualizar con el tiempo. Así que para cada nueva versión de Symfony que salga, tendrás que comparar la plantilla original con la nueva y después tendrás que incorporar los cambios a tu propia plantilla. En definitiva, que perderás mucho tiempo cada vez que actualices Symfony.

Otro motivo por el que no se deberían hacer estos cambios es que pueden confundir a otros programadores que trabajen en el proyecto (o que se incorporen en el futuro). Cuando alguien acostumbrado a Symfony ve una página de error parecida a Symfony pero con "cosas raras", como un logotipo cambiado, es seguro que eso va a confundirle.

Al margen de todo este rollo, la opción de personalizar las páginas de error en producción es una de las cosas más fáciles de hacer con Symfony. De hecho, lo único que tienes que hacer es precisamente lo que has dicho que ya has hecho:

<tu-proyecto>
|- app/
   |- Resources/
      |- TwigBundle/
         |- views/
            |- Exception/
               |- error.html.twig
               |- error404.html.twig

Crear esas dos plantillas es todo lo que tienes que hacer para personalizar en producción los errores 404 (error404.html.twig) y el resto de errores (error.html.twig).

Mi recomendación sería que eliminaras todas las plantillas de TwigBundle que has copiado y te quedaras con esas dos únicas plantillas. Después, y por si se trata de algún error raro después de tanto copia+pega de plantillas, te aconsejo que borres la caché con el comando rm -fr app/cache/* en vez de utilizar el comando cache:clear de Symfony.

@javiereguiluz

8 septiembre 2014, 12:50
#2

Hola Javier y gracias por tu respuesta.

He hecho lo que me has indicas: me he cargado todas las plantillas, lo del logotipo fue pura curiosidad para ver si la cosa andaba bien a la hora sobrescribir las plantillas.

Ahora está todo limpio solo me he quedado con esas dos que me indicas. Pero me sigue apareciendo lo mismo. He modificado las dos plantillas añadiendo en el <h1> la coletilla de Hola, Oops! An Error Occurred.

La verdad no se qué puede estar pasando, ¿podría tener algo que ver con la configuración de los vhosts?

Edito:

Yo en ningún momento mando ninguna excepción en el código PHP. Ya que igualmente no creo que haga falta ya que la URL me la estoy inventando, y no coincide con ningún controlador o ruta en este caso.

Un saludo.

@jcarlosweb

8 septiembre 2014, 13:52
#3

Estoy un poco perdido porque, como te decía antes, esta es una de las (pocas) cosas que funcionan siempre bien a la primera. En cualquier caso, lo primero que miraría es si has modificado el código del controlador de producción (web/app.php). Quizás has estado haciendo pruebas y has cambiado el valor del segundo parámetro que se pasa a AppKernel (y que en producción debe ser false).

Lo segundo que miraría es si la ruta de la plantilla de error es correcta, ya que es fácil liarse:

app/Resources/views/TwigBundle/views/Exception/error404.html.twig <-- MAL
app/Resources/TwigBundle/views/Exception/error404.html.twig       <-- BIEN

@javiereguiluz

8 septiembre 2014, 15:07
#4

Gracias Javier ya está arreglado.

Fuss que tontería más grande Exception lo tenia en plural.

Claro lo del logotipo me funcionaba porque está modificando la plantilla base que estaba fuera ´Exception´. Y yo confiado de mi, pues muchas horas perdidas.

Bueno Javier gracias por tu paciencia.

Un abrazo muy grande.

@jcarlosweb

8 septiembre 2014, 16:21
#5

Hola

Estado intentando personalizar la página de error mediante este método, pero en el template cuando escribo código simple o HTML si se muestra el contenido que pongo, pero si uso alguna función twig se me queda la página en blanco, limpié bien la caché y nada , en los logs del modo prod el contenido que aparece es

[2015-11-08 02:41:22] request.ERROR: Uncaught PHP Exception Symfony\Component\HttpKernel\Exception\NotFoundHttpException: "No route found for "GET /hosd%5D"" at /demo/vendor/symfony/symfony/src/Symfony/Component/HttpKernel/EventListener/RouterListener.php line 116 {"exception":"[object] (Symfony\\Component\\HttpKernel\\Exception\\NotFoundHttpException: No route found for \"GET /hosd%5D\" at /demo/vendor/symfony/symfony/src/Symfony/Component/HttpKernel/EventListener/RouterListener.php:116, Symfony\\Component\\Routing\\Exception\\ResourceNotFoundException:  at /demo/app/cache/prod/appProdUrlMatcher.php:302)"} []
[2015-11-08 02:41:22] request.ERROR: Exception thrown when handling an exception (Twig_Error_Runtime: An exception has been thrown during the rendering of a template ("The security context contains no authentication token. One possible reason may be that there is no firewall configured for this URL.") in "TwigBundle:Exception:error.html.twig".) {"exception":"[object] (Symfony\\Component\\HttpKernel\\Exception\\NotFoundHttpException: No route found for \"GET /hosd%5D\" at /demo/vendor/symfony/symfony/src/Symfony/Component/HttpKernel/EventListener/RouterListener.php:116, Symfony\\Component\\Routing\\Exception\\ResourceNotFoundException:  at /demo/app/cache/prod/appProdUrlMatcher.php:302)"} []

@pochy_ja

8 noviembre 2015, 9:03
#6

@pochy_ja seguramente te está pasando uno de los errores más típicos de Symfony. En la página de error 404 tienes una llamada a is_granted() y eso da error. Los detalle se explican en este artículo de la documentación de Symfony.

La solución es tan sencilla como cambia esto:

{% if is_granted('...') %}
    ...
{% endif %}

por esto:

{% if app.user and is_granted('...') %}
    ...
{% endif %}

A partir de Symfony 2.8 este problema ya desaparece y se puede usar is_granted() en cualquier página de error.

@javiereguiluz

8 noviembre 2015, 9:49
#7

Hola @javiereguiluz

Gracias por responder, la verdad es que había visto eso que mencionas y lo había quitado pero simplemente sigue sin mostrar cualquier otra cosa de Twig. Realmente lo que quiero es extender de mi plantilla base y agregar un texto interno con un par de botones, nada complicado. Lo que pasa que cuando pongo la función Twig, la página se me queda en blanco. Estoy usando Symfony2.3, el código sería algo sencillo como esto

{% extends '::base.html.twig' %}
{% block body %}
 
<h1>Page not found</h1>
 
    <p>
        The requested page couldn't be located. Checkout for any URL
        misspelling or <a href="{{ path('frontend_home') }}">return to the homepage</a>.
    </p>
{% endblock %}

Y en los logs de producción me sigue lanzando el mismo mensaje que puse en mi comentario anterior.

@pochy_ja

8 noviembre 2015, 23:03
#8

La plantilla que muestras es sencilla y todo parece correcto. Pero fíjate que hereda de ::base.html.twig, así que ahí está el problema. En la plantilla ::base.html.twig haces alguna llamada a una función que depende del sistema de seguridad de Symfony. Para solucionarlo debes añadir la condición que te indicaba antes para cualquier llamada a is_granted().

@javiereguiluz

9 noviembre 2015, 8:36
#9

Gracias @javiereguiluz

Solucionado, era una instancia de la función is_granted() que había pasado por alto en el base.

@pochy_ja

9 noviembre 2015, 19:26