runtime-handling-errors.md 8.37 KB
Newer Older
larnu committed
1
Gestión de Errores
2 3
==================

4
Yii incluye un [[yii\web\ErrorHandler|error handler]] que permite una gestión de errores mucho más práctica que
5 6
anteriormente. En particular, el gestor de errores de Yii hace lo siguiente para mejorar la gestión de errores:

7
* Todos los errores no fatales (ej. advertencias (warning), avisos (notices)) se convierten en excepciones
8
  capturables.
9
* Las excepciones y los errores fatales de PHP se muestran con una pila de llamadas (call stack) de información
larnu committed
10
  detallada y lineas de código fuente.
11 12 13
* Soporta el uso de [acciones de controlador](structure-controllers.md#actions) dedicadas para mostrar errores.
* Soporta diferentes formatos de respuesta (response) de errores.

14 15
El [[yii\web\ErrorHandler|error handler]] esta habilitado de forma predeterminada. Se puede deshabilitar definiendo la
constante `YII_ENABLE_ERROR_HANDLER` con valor false en el
16 17
[script de entrada (entry script)](structure-entry-scripts.md) de la aplicación.

18
## Uso del Gestor de Errores <span id="using-error-handler"></span>
19

20 21
El [[yii\web\ErrorHandler|error handler]] se registra como un
[componente de aplicación](structure-application-components.md) llamado `errorHandler`. Se puede configurar en la
22 23 24 25 26 27 28 29 30 31 32 33
configuración de la aplicación como en el siguiente ejemplo:

```php
return [
    'components' => [
        'errorHandler' => [
            'maxSourceLines' => 20,
        ],
    ],
];
```

34
Con la anterior configuración, el numero del lineas de código fuente que se mostrará en las páginas de excepciones
35 36
será como máximo de 20.

37
Como se ha mencionado, el gestor de errores convierte todos los errores de PHP no fatales en excepciones capturables.
38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
Esto significa que se puede usar el siguiente código para tratar los errores PHP:

```php
use Yii;
use yii\base\ErrorException;

try {
    10/0;
} catch (ErrorException $e) {
    Yii::warning("Division by zero.");
}

// la ejecución continua ...
```

53 54 55
Si se quiere mostrar una página de error que muestra al usuario que su petición no es válida o no es la esperada, se
puede simplemente lanzar una excepción de tipo [[yii\web\HttpException|HTTP exception]], como podría ser
[[yii\web\NotFoundHttpException]]. El gestor de errores establecerá correctamente el código de estado HTTP de la
56 57 58 59 60 61 62 63
respuesta y usará la vista de error apropiada para mostrar el mensaje.

```php
use yii\web\NotFoundHttpException;

throw new NotFoundHttpException();
```

64
## Personalizar la Visualización de Errores <span id="customizing-error-display"></span>
65

66 67 68 69
El [[yii\web\ErrorHandler|error handler]] ajusta la visualización del error conforme al valor de la constante
`YII_DEBUG`. Cuando `YII_DEBUG` es `true` (es decir, en modo depuración (debug)), el gestor de errores mostrara las
excepciones con una pila detallada de información y con lineas de código fuente para ayudar a depurar. Y cuando la
variable `YII_DEBUG` es `false`, solo se mostrará el mensaje de error para prevenir la revelación de información
70 71
sensible de la aplicación.

72 73
> Información: Si una excepción es descendiente de [[yii\base\UserException]], no se mostrará la pila de llamadas
  independientemente del valor de `YII_DEBUG`. Esto es debido a que se considera que estas excepciones se deben a
74 75
  errores cometidos por los usuarios y los desarrolladores no necesitan corregirlas.

76
De forma predeterminada, el [[yii\web\ErrorHandler|error handler]] muestra los errores usando dos
77 78
[vistas](structure-views.md):

79
* `@yii/views/errorHandler/error.php`: se usa cuando deben mostrarse los errores SIN la información de la pila de
80
  llamadas. Cuando `YII_DEBUG` es falos, este es el único error que se mostrara.
81
* `@yii/views/errorHandler/exception.php`: se usa cuando los errores deben mostrarse CON la información de la pila de
82 83
  llamadas.

84 85
Se pueden configurar las propiedades [[yii\web\ErrorHandler::errorView|errorView]] y
[[yii\web\ErrorHandler::exceptionView|exceptionView]] el gestor de errores para usar nuestros propias vistas para
86 87
personalizar la visualización de los errores.

88
### Uso de Acciones de Error <span id="using-error-actions"></span>
89

90 91
Una mejor manera de personalizar la visualización de errores es usar un [acción](structure-controllers.md) de error
dedicada. Para hacerlo, primero se debe configurar la propiedad [[yii\web\ErrorHandler::errorAction|errorAction]] del
92 93 94 95 96 97 98 99 100 101 102 103
componente `errorHandler` como en el siguiente ejemplo:

```php
return [
    'components' => [
        'errorHandler' => [
            'errorAction' => 'site/error',
        ],
    ]
];
```

104 105
La propiedad [[yii\web\ErrorHandler::errorAction|errorAction]] vincula una [ruta](structure-controllers.md#routes) a
una acción. La configuración anterior declara que cuando un error tiene que mostrarse sin la pila de información de
106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128
llamadas, se debe ejecutar la acción `site/error`.

Se puede crear una acción `site/error` como se hace a continuación,

```php
namespace app\controllers;

use Yii;
use yii\web\Controller;

class SiteController extends Controller
{
    public function actions()
    {
        return [
            'error' => [
                'class' => 'yii\web\ErrorAction',
            ],
        ];
    }
}
```

129
El código anterior define la acción `error` usando la clase [[yii\web\ErrorAction]] que renderiza un error usando la
larnu committed
130
vista llamada `error`.
131

132
Además, usando [[yii\web\ErrorAction]], también se puede definir la acción `error` usando un método de acción como en
133 134 135 136 137 138 139 140 141 142 143 144
el siguiente ejemplo,

```php
public function actionError()
{
    $exception = Yii::$app->errorHandler->exception;
    if ($exception !== null) {
        return $this->render('error', ['exception' => $exception]);
    }
}
```

145
Ahora se debe crear un archivo de vista ubicado en `views/sites/error.php`. En este archivo de vista, se puede acceder
146 147 148 149
a las siguientes variables si se define el error como un [[yii\web\ErrorAction]]:

* `name`: el nombre del error;
* `message`: el mensaje del error;
150
* `exception`: el objeto de excepción a través del cual se puede obtener más información útil, tal como el código de
151 152
  estado HTTP, el código de error, la pila de llamadas del error, etc.

153
> Información: Tanto la [plantilla de aplicación básica](start-installation.md) como la
154 155
  [plantilla de aplicación avanzada](tutorial-advanced-app.md), ya incorporan la acción de error y la vista de error.

156
### Personalizar el Formato de Respuesta de Error <span id="error-format"></span>
157

158 159 160 161 162
El gestor de errores muestra los errores de siguiente la configuración del formato de las
[respuestas](runtime-responses.md). Si el [[yii\web\Response::format response format]] es `html`, se usará la vista de
error o excepción para mostrar los errores tal y como se ha descrito en la anterior subsección. Para otros tipos de
formatos de respuesta, el gestor de errores asignara la representación del array de la excepción a la propiedad
[[yii\web\Response::data]] que posteriormente podrá convertirse al formato deseado. Por ejemplo, si el formato de
larnu committed
163
respuesta es `json`, obtendremos la siguiente respuesta:
164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179

```
HTTP/1.1 404 Not Found
Date: Sun, 02 Mar 2014 05:31:43 GMT
Server: Apache/2.2.26 (Unix) DAV/2 PHP/5.4.20 mod_ssl/2.2.26 OpenSSL/0.9.8y
Transfer-Encoding: chunked
Content-Type: application/json; charset=UTF-8

{
    "name": "Not Found Exception",
    "message": "The requested resource was not found.",
    "code": 0,
    "status": 404
}
```

180
Se puede personalizar el formato de respuestas de error respondiendo al evento `beforeSend` del componente `response`
larnu committed
181
en la configuración de la aplicación:
182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222

```php
return [
    // ...
    'components' => [
        'response' => [
            'class' => 'yii\web\Response',
            'on beforeSend' => function ($event) {
                $response = $event->sender;
                if ($response->data !== null) {
                    $response->data = [
                        'success' => $response->isSuccessful,
                        'data' => $response->data,
                    ];
                    $response->statusCode = 200;
                }
            },
        ],
    ],
];
```

El código anterior reformateará la respuesta de error como en el siguiente ejemplo:

```
HTTP/1.1 200 OK
Date: Sun, 02 Mar 2014 05:31:43 GMT
Server: Apache/2.2.26 (Unix) DAV/2 PHP/5.4.20 mod_ssl/2.2.26 OpenSSL/0.9.8y
Transfer-Encoding: chunked
Content-Type: application/json; charset=UTF-8

{
    "success": false,
    "data": {
        "name": "Not Found Exception",
        "message": "The requested resource was not found.",
        "code": 0,
        "status": 404
    }
}
```