Ver índice de contenidos del libro

2.6. Gestión de errores

Si el código de tu aplicación lanza una excepción, seguramente querrás mostrar una página de error al usuario. Esta es la función de los gestores de errores o "error handlers", aunque también se pueden utilizar para otras tareas, como por ejemplo guardar mensajes de log.

Los gestores de errores se registran pasando un closure al método error() de la aplicación. La función admite un objeto de tipo Exception como argumento y devuelve la respuesta enviada al usuario:

use Symfony\Component\HttpFoundation\Response;
 
$app->error(function (\Exception $e, $code) {
    return new Response('Lo sentimos pero ha sucedido un error grave.');
});

Gracias al argumento $code puedes crear diferentes páginas de error en función del tipo de excepción que se produzca:

use Symfony\Component\HttpFoundation\Response;
 
$app->error(function (\Exception $e, $code) {
    switch ($code) {
        case 404:
            $message = 'No hemos encontrado la página solicitada.';
            break;
        default:
            $message = 'Lo sentimos pero ha sucedido un error grave.';
    }
 
    return new Response($message);
});

Si utilizas un tipo específico de excepción como argumento de la función, el gestor de errores solo tratará ese tipo de excepción:

$app->error(function (\LogicException $e, $code) {
    // aqui solo se tratan las excepciones de tipo \LogicException
    // y las que hereden de \LogicException
});

Nota Como Silex siempre se asegura de que el código HTTP de la respuesta sea el más correcto en función de la excepción, no vas a poder poner el código de estado HTTP dentro del método error(). Si aún así quieres redefinir el valor del código de estado (algo que solo deberías hacer si tienes una buena razón para ello) utiliza la cabecera X-Status-Code de HTTP:

// Silex ignora el valor 404
return new Response('Error', 404, array('X-Status-Code' => 200));

Cuando se registra un gestor de errores para guardar mensajes de log, debes registrarlo antes que cualquier otro gestor de errores, ya que una vez devuelto un objeto de tipo Response, ya no se ejecutan más gestores de errores:

Nota Silex incluye un proveedor para la librería Monolog, que se encarga de guardar todos los mensajes de log. Consulta el capítulo de proveedores para obtener más detalles.

Truco Cuando la opción debug es true Silex utiliza un gestor de errores especial que muestra un montón de información sobre el error producido. Las funciones de tu aplicación encargadas de gestionar los errores siempre tienen preferencia sobre Silex, pero si quieres mantener la página de error con información detallada, utiliza un código como el siguiente:

use Symfony\Component\HttpFoundation\Response;
 
$app->error(function (\Exception $e, $code) use ($app) {
    if ($app['debug']) {
        return;
    }
 
    // código para procesar el error y devolver un objeto Response
});

Las funciones que manejan los errores también se ejecutan cuando se utiliza el método abort() para detener la ejecución de la aplicación:

$app->get('/blog/{id}', function (Silex\Application $app, $id) use ($blogPosts) {
    if (!isset($blogPosts[$id])) {
        $app->abort(404, "El post $id no existe.");
    }
 
    return new Response(...);
});