Manejo de Errores en Laravel

Aún cuando Laravel trae preconfigurado el manejo de errores, encontrarás que algunas aplicaciones necesitan ser personalizadas a los requerimientos del sistema.

Primeramente hablemos de la configuración, en el archivo config/app.php encontramos que la variable APP_DEBUG controla cuanto debe ser el detalle de los mensajes de errores. Por ello, se define que para entornos de desarrollo la variable debe ser true, y para los casos de producción debe ser false.

Ahora bien, todas la excepciones en Laravel son manejadas por la clase App\Exceptions\Handler. Esta clase contiene dos metodos: report y render.

Report

El método report es útil cuando necesitamos loguear los errores a sistemas externos. Por ejemplo, a un servidor remoto syslog. Por defecto, el método report simplemente pasa la clase base de una Excepción. Así, podríamos enviar diferente notificaciones a diferentes logs de la siguiente forma. Asimismo, podríamos guardar en el log de Laravel cualquier excepción.

/**
 * Report or log an exception.
 *
 * This is a great spot to send exceptions to Sentry, Bugsnag, etc.
 *
 * @param  \Exception  $e
 * @return void
 */
public function report(Exception $e)
{
    if ($e instanceof CustomException) {
        //
    }

    return parent::report($e);
}

Render

Este método es el responsable de convertir una excepción en una respuesta HTTP que pudiera ser enviada al navegador. Por defecto, se recibe la excepción base, sin embargo, existe la libertad de enviar a cualquier vista, como se desee.

/**
 * Render an exception into an HTTP response.
 *
 * @param  \Illuminate\Http\Request  $request
 * @param  \Exception  $e
 * @return \Illuminate\Http\Response
 */
public function render($request, Exception $e)
{
    if ($e instanceof CustomException) {
        return response()->view('errors.custom', [], 500);
    }

    return parent::render($request, $e);
}

Por otro lado, si se quiere aún mas personalización, se pueden crear vistas HTML para los diferentes códigos de estado HTTP. Es decir, si queremos singularizar los errores 404, creamos un archivo en la ruta resources/views/errors/404.blade.php. Este archivo reemplazará todos los errores 404 generados en la aplicación.

Logging

Laravel provee una capa simple para acceder a la librería Monolog. De allí que podamos escribir en el log usando el facade Log.

<?php

namespace App\Http\Controllers;

use Log;
use App\User;
use App\Http\Controllers\Controller;

class UserController extends Controller
{
    /**
     * Show the profile for the given user.
     *
     * @param  int  $id
     * @return Response
     */
    public function showProfile($id)
    {
        Log::info('Showing user profile for user: '.$id);

        return view('user.profile', ['user' => User::findOrFail($id)]);
    }
}

Con ello, pudiéramos integrar el uso de log para la captura de errores pudieran no ser vistos por el usuario en el navegador. Supongamos, que no se encuentra el perfil por el id, allí tendríamos un error de aplicación. Aquí podemos captura el error y agregarlo al log, de la siguiente forma

<?php

namespace App\Http\Controllers;

use Log;
use App\User;
use App\Http\Controllers\Controller;
use Illuminate\Database\Eloquent\ModelNotFoundException;

class UserController extends Controller
{
    /**
     * Show the profile for the given user.
     *
     * @param  int  $id
     * @return Response
     */
    public function showProfile($id)
    {
        try {
            return view('user.profile', ['user' => User::findOrFail($id)]);
        catch (ModelNotFoundException $e) {       
            Log::error('User not found with id '.$id);
        }

        return view('user.index');
    }
}

Así, el usuario no se enteraría del error, y los administrador pudieran estar monitoreando el log para posibles errores.