() translation by (you can also view the original English article)
En este artículo, vamos a explorar una de las características más importantes y menos discutidas del marco de trabajo web Laravel---manejo de excepciones. Laravel viene con un manejador de excepciones integrado que te permite reportar y generar excepciones de manera sencilla y amigable.
En la primera mitad del artículo, vamos a explorar los ajustes por defecto proporcionados por el manejador de excepciones. De hecho, recorreremos la clase Handler por defecto en primer lugar para entender cómo maneja excepciones Laravel.
En la segunda mitad del artículo, vamos a continuar y ver cómo podrías crear un manejador de excepciones personalizado que te permita atrapar excepciones personalizadas.
Configurando los Pre-requisitos
Antes de continuar y sumergirnos en la clase Handler, echemos un vistazo a un par de importantes parámetros de configuración relacionados con excepciones.
Continua y abre el archivo config/app.php
. Echemos un
vistazo de cerca al siguiente código.
1 |
...
|
2 |
...
|
3 |
/*
|
4 |
|--------------------------------------------------------------------------
|
5 |
| Application Debug Mode
|
6 |
|--------------------------------------------------------------------------
|
7 |
|
|
8 |
| When your application is in debug mode, detailed error messages with
|
9 |
| stack traces will be shown on every error that occurs within your
|
10 |
| application. If disabled, a simple generic error page is shown.
|
11 |
|
|
12 |
*/
|
13 |
|
14 |
'debug' => env('APP_DEBUG', false), |
15 |
...
|
16 |
...
|
Como el nombre sugiere, si se establece a TRUE
, te ayudará a
depurar errores que son generados por una aplicación. El valor por defecto de
esta variable está establecido al valor de la variable de entorno APP_DEBUG
en
el archivo .env
.
En el entorno de desarrollo, deberías establecerla a TRUE
para que puedas detectar fácilmente errores y repararlos. Por otro lado,
querrás apagarlo en el entorno de producción, y mostrará una página genérica de
error en ese caso.
En adición a mostrar errores, Laravel te permite registrar
errores en el archivo de registro. Echemos un vistazo rápido a las opciones
disponibles para registrar. De nuevo, cambienmos al archivo config/app.php
y
echemos un vistazo cercano al siguiente código.
1 |
...
|
2 |
...
|
3 |
'log' => env('APP_LOG', 'single'), |
4 |
|
5 |
'log_level' => env('APP_LOG_LEVEL', 'debug'), |
6 |
...
|
7 |
...
|
Ya que Laravel usa la librería Monolog PHP para registrar, deberías establecer las opciones de arriba en el contexto de esa librería.
El archivo de registro por defecto está ubicado en storage/logs/laravel.log
,
y es suficiente en la mayoría de los casos. Por otro lado, el APP_LOG_LEVEL
está establecido a un valor que indica la severidad de los errores que serán
registrados.
Así que esa es la introducción básica a las opciones de configuración disponibles para excepciones y registro.
A continuación, echemos un vistazo a la clase Handler por
defecto que viene con la aplicación por defecto de Laravel. Continua y abre el
archivo app/Exceptions/Handler.php
.
1 |
<?php
|
2 |
|
3 |
namespace App\Exceptions; |
4 |
|
5 |
use Exception; |
6 |
use Illuminate\Auth\AuthenticationException; |
7 |
use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler; |
8 |
|
9 |
class Handler extends ExceptionHandler |
10 |
{
|
11 |
/**
|
12 |
* A list of the exception types that should not be reported.
|
13 |
*
|
14 |
* @var array
|
15 |
*/
|
16 |
protected $dontReport = [ |
17 |
\Illuminate\Auth\AuthenticationException::class, |
18 |
\Illuminate\Auth\Access\AuthorizationException::class, |
19 |
\Symfony\Component\HttpKernel\Exception\HttpException::class, |
20 |
\Illuminate\Database\Eloquent\ModelNotFoundException::class, |
21 |
\Illuminate\Session\TokenMismatchException::class, |
22 |
\Illuminate\Validation\ValidationException::class, |
23 |
];
|
24 |
|
25 |
/**
|
26 |
* Report or log an exception.
|
27 |
*
|
28 |
* This is a great spot to send exceptions to Sentry, Bugsnag, etc.
|
29 |
*
|
30 |
* @param \Exception $exception
|
31 |
* @return void
|
32 |
*/
|
33 |
public function report(Exception $exception) |
34 |
{
|
35 |
parent::report($exception); |
36 |
}
|
37 |
|
38 |
/**
|
39 |
* Render an exception into an HTTP response.
|
40 |
*
|
41 |
* @param \Illuminate\Http\Request $request
|
42 |
* @param \Exception $exception
|
43 |
* @return \Illuminate\Http\Response
|
44 |
*/
|
45 |
public function render($request, Exception $exception) |
46 |
{
|
47 |
return parent::render($request, $exception); |
48 |
}
|
49 |
|
50 |
/**
|
51 |
* Convert an authentication exception into an unauthenticated response.
|
52 |
*
|
53 |
* @param \Illuminate\Http\Request $request
|
54 |
* @param \Illuminate\Auth\AuthenticationException $exception
|
55 |
* @return \Illuminate\Http\Response
|
56 |
*/
|
57 |
protected function unauthenticated($request, AuthenticationException $exception) |
58 |
{
|
59 |
if ($request->expectsJson()) { |
60 |
return response()->json(['error' => 'Unauthenticated.'], 401); |
61 |
}
|
62 |
|
63 |
return redirect()->guest(route('login')); |
64 |
}
|
65 |
}
|
Hay dos funciones importantes por las que es responsable la clase handler---repoerar y generar todos los errores.
Echemos un vistazo al método report
.
1 |
/**
|
2 |
* Report or log an exception.
|
3 |
*
|
4 |
* This is a great spot to send exceptions to Sentry, Bugsnag, etc.
|
5 |
*
|
6 |
* @param \Exception $exception
|
7 |
* @return void
|
8 |
*/
|
9 |
public function report(Exception $exception) |
10 |
{
|
11 |
parent::report($exception); |
12 |
}
|
El método report es usado para registrar errores al archivo
de bitácora. Al mismo tiempo, también es importante notar la propiedad
dontReport
, la cual lista todos los tipos de excepciones que no deberían ser registradas.
A continuación, traigamos el método render
.
1 |
/**
|
2 |
* Render an exception into an HTTP response.
|
3 |
*
|
4 |
* @param \Illuminate\Http\Request $request
|
5 |
* @param \Exception $exception
|
6 |
* @return \Illuminate\Http\Response
|
7 |
*/
|
8 |
public function render($request, Exception $exception) |
9 |
{
|
10 |
return parent::render($request, $exception); |
11 |
}
|
Si el método report
es usado para registrar o reportar
errores, el método render
es usado para generar errores en una pantalla. De
hecho, este método maneja lo que será mostrado a los usuarios cuando ocurre una
excepción.
El método render
también te permite personalizar una
respuesta para diferentes tipos de excepciones, como veremos en la siguiente
sección.
Finalmente, el método unauthenticated
maneja la excepción AuthenticationException
que te permite decidir lo que será mostrado a los usuarios en caso de que no
estén autenticados para acceder a la página que están buscando.
Clase de Excepción Personalizada
En esta sección, crearemos una clase de excepción
personalizada que maneje excepciones del tipo CustomException
. La idea detrás
de crear clases de excepción personalizada es administrar fácilmente
excepciones personalizadas y generar respuesta personalizadas al mismo tiempo.
Continua y crea un archivo app/Exceptions/CustomException.php
con el siguiente contenido.
1 |
<?php
|
2 |
|
3 |
namespace App\Exceptions; |
4 |
|
5 |
use Exception; |
6 |
|
7 |
class CustomException extends Exception |
8 |
{
|
9 |
/**
|
10 |
* Report the exception.
|
11 |
*
|
12 |
* @return void
|
13 |
*/
|
14 |
public function report() |
15 |
{
|
16 |
}
|
17 |
|
18 |
/**
|
19 |
* Render the exception into an HTTP response.
|
20 |
*
|
21 |
* @param \Illuminate\Http\Request
|
22 |
* @return \Illuminate\Http\Response
|
23 |
*/
|
24 |
public function render($request) |
25 |
{
|
26 |
return response()->view( |
27 |
'errors.custom', |
28 |
array( |
29 |
'exception' => $this |
30 |
)
|
31 |
);
|
32 |
}
|
33 |
}
|
Lo importante a notar aquí es que la clase CustomException
debe extender a la clase principal Exception
. Para propósitos de la
demostración, solo discutiremos el método render, pero claro que podrías
también personalizar el método report.
Como puedes ver, estamos redirigiendo a los usuarios a la
página de error errors.custom
en nuestro caso. De esa manera, puedes
implementar páginas de error personalizadas para tipos específicos de
excepciones.
Por supuesto, necesitamos crear un archivo de vista asociado
en resources/views/errors/custom.blade.php
.
1 |
Exception details: <b>{{ $exception->getMessage() }}</b> |
Ese es un archivo de vista muy simple que muestra un mensaje de error, pero por supuesto podrías diseñarlo de la manera que quieres que sea.
También necesitamos hacer cambios en el método de generación del archivo app/Exceptions/Handler.php
para que nuestra clase personalizada de excepción pueda ser invocada. Reemplacemos el método render con los siguientes contenidos en el archivo app/Exceptions/Handler.php
.
1 |
...
|
2 |
...
|
3 |
/**
|
4 |
* Render an exception into an HTTP response.
|
5 |
*
|
6 |
* @param \Illuminate\Http\Request $request
|
7 |
* @param \Exception $exception
|
8 |
* @return \Illuminate\Http\Response
|
9 |
*/
|
10 |
public function render($request, Exception $exception) |
11 |
{
|
12 |
if ($exception instanceof \App\Exceptions\CustomException) { |
13 |
return $exception->render($request); |
14 |
}
|
15 |
|
16 |
return parent::render($request, $exception); |
17 |
}
|
18 |
...
|
19 |
...
|
Como puedes ver, estamos revisando el tipo de una excepción en el método de generación en primer lugar. Si el tipo de una excepción es \App\Exceptions\CustomException
, llamamos al método de generación de esa clase.
Así que todo está en su lugar ahora. Después, continua y crea un archivo controlador en app/Http/Controllers/ExceptionController.php
para que podamos probar nuestra clase personalizada de excepción.
1 |
<?php
|
2 |
namespace App\Http\Controllers; |
3 |
|
4 |
use App\Http\Controllers\Controller; |
5 |
|
6 |
class ExceptionController extends Controller |
7 |
{
|
8 |
public function index() |
9 |
{
|
10 |
// something went wrong and you want to throw CustomException
|
11 |
throw new \App\Exceptions\CustomException('Something Went Wrong.'); |
12 |
}
|
13 |
}
|
Por supuesto, necesitas crear una ruta asociada en routes/web.php
como se muestra en el siguiente código.
1 |
// Exception routes
|
2 |
Route::get('exception/index', 'ExceptionController@index'); |
Y con eso en su lugar, puedes ejecutar la URL http://your-laravel-site.com/exception/index para ver si funciona como se espera. Debería mostrar la vista errors.custom
como nuestra configuración.
Así es como se supone que manejes excepciones personalizadas en Laravel. Y eso nos lleva al final de este artículo---¡espero que lo hayas disfrutado!
Conclusión
Hoy, recorrimos la característica de manejo de excepción en Laravel. Al inicio del artículo, exploramos la configuración básica provista por Laravel para generar y reportar excepciones. Más adelante, echamos un vistazo breve a la clase manejadora de excepción por defecto.
En la segunda mitad del artículo, preparamos una clase de excepción personalizada que te demostró como podrías manejar excepciones personalizadas en tu aplicación.
Para aquellos de ustedes que están comenzando con Laravel o están buscando expandir su conocimiento, sitio o aplicación con extensiones, tenemos una variedad de cosas que puedes estudiar en Envato Market.
¡Me encantaría escuchar de ti en forma de preguntas y sugerencias!